浅谈JavaScript中继承的实现
谈到js中的面向对象编程,都有一个共同点,选择原型属性还是构造函数,两者各有利弊,而就片面的从js的对象创建以及继承的实现两个方面来说,官方所推荐的是两个相结合,各尽其责,各取其长,在前面的例子中,我已就在JavaScript中对象创建的方法做了一些总结,下面就其继承来道说一二:
1:原型链继承:
每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象内部的指针
(默认的原型,所有默认类型都继承了Object,而这个继承也是用过原型链实现)
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //继承SuperType SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function(){ return this.subproperty; }; var instance = new SubType(); alert(instance.property); alert(instance.getSuperValue()); alert(instance.getSubValue());
原型继承的问题:
1:原型属性被所有实例所共享 一个改变,其余跟着改变。
2:在创建子类型的实例时,不能向超类型的构造函数中传递参数
总结:实践中很少会单独使用原型链
(这似乎和对象创建时的问题如出一辙)
2:借用构造函数创建:
function SuperType(){ this.colors = ["red","blue","green"]; } function SubType(){ // 继承了SubType SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors); //["red", "blue", "green", "black"] var instance2 = new SubType() alert(instance2.colors); //["red", "blue", "green"]没哟随某个实例
//的更改而更改
//-------------------------------------------------------------------------- // 参数传递: function SuperType(name){ this.name = name; } function SubType(){ // 继承了SuperType,同时还传递了参数 SuperType.call(this , "Nicholas"); // 实例属性 this.age = 29; } var instance = new SubType(); alert(instance.name); //Nicholas alert(instance.age); //29
缺点:方法都在构造函数里面定义,因此函数复用就无从谈起(什么意思呢:摸索中)。
组合继承:
// 组合继承: 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);//第一次调用SuperType() this.age = age; } //继承方法: SubType.prototype = new SuperType(); //第二次调用SuperType() SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); }; var instance1 = new SubType("Nicholas",29); instance1.colors.push("black"); alert(instance1.colors); instance1.sayName(); instance1.sayAge(); var instance2 = new SubType("Greg",27); alert(instance2.colors); instance2.sayName(); instance2.sayAge();
自然,这种组合式创建也有其不到之处,即来两次调用了SuperType构造函数,使得实例属性colors和name的重复创建,后一次创建的自然会覆盖前面的。
随引出<寄生组合式继承>
上代码:
//寄生组合式继承: function inheritPrototype(subType , superType){ var prototype = Object(superType.prototype); //创建对象原型的一
//个副本
//为创建的副本添加constructor属性,使其指向自己的构造函数 prototype.constructor = subType;//将新创建(副本)的对象赋给子类型的一个原型
subType.prototype = prototype; } 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; } inheritPrototype(SubType , SuperType); SubType.prototype.sayAge = function(){ alert(this.age); };
从代码中,咋们可以看出,值调用了一次SuperType的构造函数,固然就没有什么多余的不必要的属性创建。
use some of my own time, creativity, energy and talent to help people.