继承
将原型链作为实现继承的主要方法。
原型链
其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
function Father(){
this.name = "father";
this.sayName = function(){
console.log(this.name);
}
}
Father.prototype.getFather = function(){
return this.name;
}
function Son(){
this.name = "son";
}
Son.prototype = new Father(); //继承Father的方法
var test = new Son();
test.sayName();//son
在通过原型链实现继承时,不能使用对象字面量创建原型方法,因为这样会重写原型链。
组合继承
使用原型链实现原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承。
function A(name){
this.name = name;
this.content=["A","B","C"];
}
A.prototype.sayName = function(){
console.log(this.name);
}
function B(name,age){
//继承属性
A.call(this,name);
this.age = age;
}
//继承方法
B.prototype = new A();
B.prototype.constructor = B;
B.prototype.sayAge = function(){
console.log(this.age);
}
var test = new B("Tom",11);
test.content.push("D","E");
console.log(test.content);//["A", "B", "C", "D", "E"]
test.sayName();//Tom
test.sayAge();//11
var test2 = new B("Sarra",22);
test2.content.push("G","H");
console.log(test2.content);//["A", "B", "C", "G", "H"]
test2.sayName();//Sarra
test2.sayAge();//22
原型式继承
借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。
function object(o){
function F(){}
F.prototype = o;
return new F();
}
实质上,object()对传入其中的对象执行了一次浅复制。
在ES5中有Object.create()
方法规范了原型式继承
var A = {
name:"A",
friends : ["B","C"]
};
var sub = Object.create(A);
sub.name = "sub";
sub.friends.push("Tom","Jerry");
console.log(sub.name);//sub
console.log(sub.friends);//["B", "C", "Tom", "Jerry"]
var b = Object.create(A);
b.name = "b";
b.friends.push("Book","May");
console.log(b.name);//b
console.log(b.friends);//["B", "C", "Tom", "Jerry", "Book", "May"]
但是看结果可以看见,原型式继承只适合需要一个对象和另一个对象保持类似的情况下。毕竟原型式继承的实例它们无法拥有各自独立的属性或方法。
寄生式继承
创建一个仅用于封装继承过程的函数
function createAnother(original){
var clone = object(original);
clone.sayHi = function(){
console.log("hi");
};
return clone;
}
var A = {
name:"A",
friends : ["B","C"]
};
var test = createAnother(A);
test.sayHi();//hi
console.log(test.friends);//["B", "C"]
在主要考虑对象而不是自定义类型和构造函数的情况下,寄生式继承也是一种有用的模式。
寄生组合式继承
function inheritPrototype(subType,superType){
var prototype = Object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function A(name){
this.name = name;
this.content=["A","B","C"];
}
A.prototype.sayName = function(){
console.log(this.name);
}
function B(name,age){
//继承属性
A.call(this,name);
this.age = age;
}
//继承方法
inheritPrototype(B,A);
B.prototype.sayAge = function(){
console.log(this.age);
}
var test = new B("Tom",11);
test.content.push("D","E");
console.log(test.content);//["A", "B", "C", "D", "E"]
test.sayName();//Tom
test.sayAge();//11
var test2 = new B("Sarra",22);
test2.content.push("G","H");
console.log(test2.content);//["A", "B", "C", "G", "H"]
test2.sayName();//Sarra
test2.sayAge();//22
优势在于只调用了一次A构造函数,避免了在B.prototype上面创建不必要的多余的属性。而且原型链不变。