javaScript中的对象的继承代码解析
借用构造函数实现继承
function supertype(){ this.colors = ["red","blue","green"]; } function subtype(){ //在子类构造函数中调用父类构造函数(同时这种方式支持向父类构造函数传参) supertype.call(this); //supertype.call(this,arg1,arg2) //supertype.apply(this,args) }
作用:借用构造函数方式是在新的subtype对象上面执行supertype中定义的初始化代码,针对在原型中的引用类型,每一个实例都有自己的一个副本(可以清除原型中包含引用类型值的问题)
问题:仅仅是借用构造函数,无法避免构造函数模式存在的问题,方法都是在构造函数中定义,因此函数复用就无从谈起了
组合继承(经典继承)
这种方式的思想是使用原型实现对原型属性和方法的继承,而通过构造函数实现对实例属性的继承
function supertype(name){ this.name = name; this.colors = ["red","blue","green"]; } //父类原型的属性和方法 supertype.prototype.sayname = function(){ alert(this.name); } function subtype(name,age){ //通过调用父类的构造方法继承父类的实例属性 supertype.call(this,name); //自己的实例属性 this.age = age; } //通过原型方式继承父类 subtype.prototype = new supertype(); //重写constructor属性 subtype.prototype.constructor = subtype; subtype.ptototype.sayage = function(){ alert(this.age); }
组合继承避免了原型链和借用构造函数的缺陷,融合了他们的优点,是javascript中最常用的一种继承模式。
问题:组合继承会导致父类构造方法被调用两次,当我们在创建子类原型的时候会调用一次,第二次是我们调用子类构造方法的时候里面会调用一次。
原型式继承
借助原型可以基于已有对象创建新的对象,同时还不必因此创建自定义类型
var person = { name:"sc", friends:["nix","unix","windows","ubantu"] } function object(o){ //临时构造函数 function f(){}; //继承 f.prototype = o; return new f(); } var p1 = object(person); p1.friends.push("p1's friends"); p1.name = "p1"; var p2 = object(person); p2.friends.push("p2's friends"); p2.name = "p2"; console.log(p1.name);//p1 console.log(p2.name);//p2 console.log(p1.friends);//["nix", "unix", "windows", "ubantu", "p1's friends", "p2's friends"] console.log(p2.friends);//["nix", "unix", "windows", "ubantu", "p1's friends", "p2's friends"]
上面的原型方式在ecmscript5中通过新增object.create()方法规范化了,该方法接收两个参数,第一个为用作新对象原型的对象和(可选的)一个新对象定义额外属性的对象。
问题:原型式继承同样没有解决引用问题
寄生式继承
寄生式继承思路与寄生构造函数类似,也就是创建一个仅仅用于封装继承过程的函数,该函数内部以某种方式来增强对象,最后再像真正的地是它做了所有的工作一样返回对象。
//寄生式继承 function createanother(original){ //调用函数创建一个新的对象 var clone = object(original); //以某种方式来增强这个对象 clone.sayhi = function(){ alert("hi"); } return clone; } //上面的object()函数不是必须的,每一个能够返回新对象的函数都可以适用这个模式
问题:可以使用寄生继承来为对象添加函数,会由于不能做到函数复用而降低效率,这一点会与构造函数模式类似。
寄生组合式继承
寄生组合式继承解决组合继承中两次调用父类构造函数的问题。寄生组合式继承,也就是通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。
思路是:不必为了指定子类的原型而调用超类的构造函数,我们所需要的无非就是超类型原型的一个副本而已,本质上,就是使用寄生继承来继承超类原型,然后再将结果指定给子类型的原型
function inheritprototype(subtype,supertype){ //创建对象 var prototype = object(supertype.prototype); //增强对象 prototype.constructor = subtype; //指定对象 subtype.prototype = prototype; }