理解继承:
继承用于在创建子类时,可以调用父类的方法和使用父类定义的变量。 javascript本身没有提供继承的关键字, 而是通过原型链的方式,达到的继承这种效果(即调用父类方法,父类基本变量copy), 然而javascript 对于父类引用类型的,子类在使用时,使用的是同一份地址,所以如果需求是如此,就没问题, 否则,需要重新在子类中重新定义自己的引用类型,因为javascript没有static 这个含义。
下面会通过一系列演变,最终达到我们所希望的继承效果。
1. 原型链
e.g.
function SuperType() {
this.property = true;
this.colors = ['red','blue','green'];
}
SuperType.prototype.getSuperValue = function() {
return this.property;
};
function SubType() {
this.subproperty = false;
}
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function() {
return this.subproperty;
};
var instance1 = new SubType();
alert(instance1.getSuperValue());
instance1.colors.push('black');
alert(instance1.colors);
var instance2 = new SubType();
alert(instance2.colors);
问题:
1. 父类定义的引用类型变量,子类在创建时会拥有改变量,但此时效果如何在子类上创建一个原型引用属性一样, 而通过子类创建的变量在修改时,会修改到同一份地址,这必然不是我们想要的
2. 在创建子类同时,不能像父类构造函数传递参数
2.借用构造函数
e.g.
function SuperType(name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
this.sayColor = function() {
return this.colors;
}
function SubType() {
SuperType.call(this,' Nicholas');
this.age = 29;
}
var instance1 = new SubType();
instance1.colors.push('black');
alert(instance1.colors);
var instance2 = new SubType();
alert(instance2.colors);
alert(instance1.name);
alert(instance1.age);
alert(instance1.sayColor == instance2.sayColor); //false
优点:
1.通过 call 改变父类作用域,达到了对于引用类型不共用同一份的问题。
问题:
1.但无法使用函数复用了,在实例子类时,父类定义的函数也会重新copy
3.组合继承
e.g.
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();
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();
优点:
1.融合原型链和借用构造函数, 堪称完美的方式
问题:
1.美中不足是 SuperType() 会调用2次
4.原型式继承
e.g.
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
var person = {
name:'Nicholas',
friends: ['Shelby', 'Court', 'Van'],
sayColor: function() {
return 'blue';
}
};
var anotherPerson = object(person);
anotherPerson.name = 'Greg';
anotherPerson.friends.push('Rob');
var yetAnotherPerson = object(person);
yetAnotherPerson.name = 'Linda';
yetAnotherPerson.friends.push('Barbie');
alert(person.friends);
alert(anotherPerson.sayColor == yetAnotherPerson.sayColor);
equals:
ECMAScript5版本
var person = {
name:'Nicholas',
friends: ['Shelby', 'Court', 'Van'],
sayColor: function() {
return 'blue';
}
};
var anotherPerson = Object.create(person);
anotherPerson.name = 'Greg';
alert(anotherPerson.name);
anotherPerson.friends.push('Rob');
var yetAnotherPerson = Object.create(person);
alert(yetAnotherPerson.name);
yetAnotherPerson.name = 'Linda';
alert(yetAnotherPerson.name);
yetAnotherPerson.friends.push('Barbie');
alert(person.friends);
alert(anotherPerson.sayColor == yetAnotherPerson.sayColor);
注: 原型式继承也是一种不错的继承方式, 子类变量的修改并不会影响父类的prototype属性,方法也达到了共用, 唯一有点影响的事, 引用类型会始终共享相应的值。
5. 寄生式继承
e.g.
function createAnother(original) {
var clone = Object.create(original);
clone.sayHi = function() {
alert("hi");
};
return clone;
}
var person = {
name: 'Nichoals',
friends: ['Shelby', 'Court', 'Van']
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi();
注: 使用集成式函数,缺点是函数不能复用, 这一点同构造函数类似
6.寄生组合式继承
e.g.
function inheritPrototype(subType, superType) {
var prototype = Object.create(superType.prototype);
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);
};
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();
注: 完美