function Parent(){ this.name = 'web前端'; this.type = ['JS','HTML','CSS'];}Parent.prototype.Say=function(){ console.log(this.name);}function Son(){};Son.prototype = new Parent();son1 = new Son();son1.Say();
以上例子阐明:
①创建一个叫做Parent的布局函数,暂且称为父布局函数,里面有两个属性name、type
②通过Parent布局函数的属性(即原型工具)设置Say方法,此时,Parent有2个属性和1个方法

③创建一个叫做Son的布局函数,暂且称为子布局函数
④设置Son的属性(即原型工具)值为父布局函数Parent的实例工具,即子布局函数Son继续了父布局函数Parent,此时Son也有2个属性和1个方法
⑤对Son布局函数进行实例化,结果赋值给变量son1,即son1为实例化工具,同样拥有2个属性和1个方法
⑥输出son1的Say方法,结果为"web前端"
优点:可以实现继续
缺陷:
①由于Son.prototype(即原型工具)继续了Parent实例化工具,这就导致了所有Son实例化工具都一样,都共享有原型工具的属性及方法。代码如下:
son1 = new Son();son2 = new Son();son1.type.push('VUE');console.log(son1.type);//['JS','HTML','CSS','VUE']console.log(son2.type);//['JS','HTML','CSS','VUE']
结果son1、son2都是['JS','HTML','CSS','VUE']
②Son布局函数实例化工具无法进行参数的通报
第二种:布局函数继续通过布局函数call方法进行继续,直接来看代码:
function Parent(){ this.name = 'web前端'; this.type = ['JS','HTML','CSS'];}function Son(){ Parent.call(this);}son1 = new Son();son1.type.push('VUE');console.log(son1.type);//['JS','HTML','CSS','VUE']son2 = new Son();console.log(son2.type);//['JS','HTML','CSS']
以上例子阐明:
①创建父级布局函数Parent,有name、type两个属性
②创建子级布局函数Son,函数内部通过call方法调用父级布局函数Parent,实现继续
③分别创建布局函数Son的两个实例化工具son1、son2,对son1的type属性新增元素,son2没有新增,结果不一样,解释实现了独立
优点:
①实现实例化工具的独立性;
②还可以给实例化工具添加参数
function Parent(name){ this.name = name;}function Son(name){ Parent.call(this,name);}son1 = new Son('JS');console.log(son1);//JSson2 = new Son('HTML');console.log(son2);//HTML
缺陷:
①方法都在布局函数中定义,每次实例化工具都得创建一遍方法,基本无法实现函数复用
②call方法仅仅调用了父级布局函数的属性及方法,没有办法调用父级布局函数原型工具的方法
第三种:组合继续利用原型链继续和布局函数继续的各自上风进行组合利用,还是看代码:
function Parent(name){ this.name = name; this.type = ['JS','HTML','CSS'];}Parent.prototype.Say=function(){ console.log(this.name);}function Son(name){ Parent.call(this,name);}Son.prototype = new Parent();son1 = new Son('张三');son2 = new Son('李四');son1.type.push('VUE');son2.type.push('PHP');console.log(son1.type);//['JS','HTML','CSS','VUE']console.log(son2.type);//['JS','HTML','CSS','PHP']son1.Say();//张三son2.Say();//李四
以上例子阐明:
①创建一个叫做Parent的布局函数,里面有两个属性name、type
②通过Parent布局函数的属性(即原型工具)设置Say方法,此时,Parent有2个属性和1个方法
③创建子级布局函数Son,函数内部通过call方法调用父级布局函数Parent,实现继续
④子布局函数Son继续了父布局函数Parent,此时Son也有2个属性和1个方法
⑤分别创建布局函数Son的两个实例化工具son1、son2,传不同参数、给type属性新增不同元素、调用原型工具Say方法
优点:
①利用原型链继续,实现原型工具方法的继续
②利用布局函数继续,实现属性的继续,而且可以参数
组合函数基本知足了JS的继续,比较常用
缺陷:
无论什么情形下,都会调用两次父级布局函数:一次是在创建子级原型的时候,另一次是在子级布局函数内部
第四种:原型式继续创建一个函数,将参数作为一个工具的原型工具
function fun(obj) { function Son(){}; Son.prototype = obj; return new Son();}var parent = { name:'张三'}var son1 = fun(parent);var son2 = fun(parent);console.log(son1.name);//张三console.log(son2.name);//张三
以上例子阐明:
①创建一个函数fun,内部定义一个布局函数Son
②将Son的原型工具设置为参数,参数是一个工具,完成继续
③将Son实例化后返回,即返回的是一个实例化工具
优缺陷:跟原型链类似
第五种:寄生继续在原型式继续的根本上,在函数内部丰富工具
function fun(obj) { function Son() { }; Son.prototype = obj; return new Son();}function JiSheng(obj) { var clone = fun(obj); clone.Say = function () { console.log('我是新增的方法'); } return clone;}var parent = { name: '张三'}var parent1 = JiSheng(parent);var parent2 = JiSheng(parent);console.log(parent2.Say==parent1.Say);// false
以上例子阐明:
①在原型式继续的根本上,封装一个JiSheng函数
②将fun函数返回的工具进行增强,新增Say方法,末了返回
③调用JiSheng函数两次,分别赋值给变量parent1、parent2
④比拟parent1、parent2,结果为false,实现独立
优缺陷:跟布局函数继续类似,调用一次函数就得创建一遍方法,无法实现函数复用,效率较低
这里补充一个知识点,ES5有一个新的方法Object.create(),这个方法相称于封装了原型式继续。这个方法可以吸收两个参数:第一个是新工具的原型工具(可选的),第二个是新工具新增属性,以是上面代码还可以这样:
function JiSheng(obj) { var clone = Object.create(obj); clone.Say = function () { console.log('我是新增的方法'); } return clone;}var parent = { name: '张三'}var parent1 = JiSheng(parent);var parent2 = JiSheng(parent);console.log(parent2.Say==parent1.Say);// false
第六种:寄生组合继续
利用组合继续和寄生继续各自上风
组合继续方法我们已经说了,它的缺陷是两次调用父级布局函数,一次是在创建子级原型的时候,另一次是在子级布局函数内部,那么我们只须要优化这个问题就行了,即减少一次调用父级布局函数,恰好利用寄生继续的特性,继续父级布局函数的原型来创建子级原型。
function JiSheng(son,parent) { var clone = Object.create(parent.prototype);//创建工具 son.prototype = clone; //指定工具 clone.constructor = son; //增强工具}function Parent(name){ this.name = name; this.type = ['JS','HTML','CSS'];}Parent.prototype.Say=function(){ console.log(this.name);}function Son(name){ Parent.call(this,name);}JiSheng(Son,Parent);son1 = new Son('张三');son2 = new Son('李四');son1.type.push('VUE');son2.type.push('PHP');console.log(son1.type);//['JS','HTML','CSS','VUE']console.log(son2.type);//['JS','HTML','CSS','PHP']son1.Say();//张三son2.Say();//李四
以上例子阐明:
①封装一个函数JiSheng,两个参数,参数1为子级布局函数,参数2为父级布局函数
②利用Object.create(),将父级布局函数原型克隆为副本clone
③将该副本作为子级布局函数的原型
④给该副本添加constructor属性,由于③中修正原型导致副本失落去默认的属性
优缺陷:
组合继续优点、寄生继续的优点,目前JS继续中利用的都是这个继续方法
总结
想要更好的理解JS继续办法,须理解布局函数、原型工具、实例化工具、原型链等观点。
我是@半糖学前端 ,专注前端技能领域分享,一个前端从业者,关注我和我一起学习,共同进步!
5个JavaScript技巧让你成为更好的开拓者
必考知识点-JavaScript类型转换(讲事理)
前端84个常用的JS代码片段,方便你学习和利用
「干货分享」前端口试知识点锦集(JavaScript篇)
36 N 个事情中常用的 JavaScript 函数片段
细品269个JavaScript小函数,让你少加班熬夜(五)「值得收藏」
JavaScript深入理解之原型与原型链
前端这么骚的 js 代码,不怕被揍么