原型链
ECMAScript将原型链作为实现 继承的主要方法,思想是,利用原型链让一个引用类型继承另一个引用类型的属性和方法
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。假如让原型对象等于另一个类型的实例,此时,此时的原型对象将包含一个指向另一个原型的指针,相应的,另一个原型中也包含着一个指向另一个构造函数的指针。
function SuperType(){
this.property = true;//父类有个property的属性
}
SuperType.prototype.getSuperValue = function(){
return this.property;//父类有个getSuperValue的方法
};
function SubType(){//子类有个subproperty的属性
this.subproperty = false;
}
//继承了父类
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function(){
return this.subproperty;
};
var instance = new SubType();
console.log(instance.getSuperValue());//true
console.log(instance instanceof Object);//true
console.log(instance instanceof SuperType);//true
console.log(instance instanceof SubType);//true
console.log("--"+Object.prototype.isPrototypeOf(instance));//true
console.log("--"+SuperType.prototype.isPrototypeOf(instance));//true
console.log("--"+SubType.prototype.isPrototypeOf(instance));//true
//解释:以上定义了两个类型SuperType和SubType,每个类型分别有一个属性和方法,SubType继承了SuperType
//1、别忘记默认的原型 Object
//2、确定原型和实例的关系
//第1中方法 alert(instance instanceof Object);
//第2中方法 alert(Object.prototype.isPrototypeOf(instance));//true
//3、谨慎的定义方法
//==========================================
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;
};
SubType.prototype.getSuperValue = function(){//重写超类的方法
return false;
};
var instance = new SubType();
alert(instance.getSubValue());//false
用字面量添加新方法,会导致SubType.property = new SuperType();代码无效
//4、原型链的问题,引用类型的值的原型属性会被所有实例共享;创建子类的实例时,不能向超类的构造函数中传递参数
function SuperType(){
this.colors = ["red","blue","green"];
}
function SubType(){
}
SubType.prototype = new SuperType();
var instance1 = new SubType();
instance1.colors.push("black");//red blue green black
alert(instance1.colors);
var instance2 = new SubType();
alert(instance2.colors);//red blue green black
//借用构造函数
//即在子类的构造函数内部调用超类的构造函数。函数只不过是在特定环境中执行代码的对象,因此通过使用apply() call()可以在(将来)新创建的对象执行构造函数
function SuperType(){
this.colors = ["red","blue","green"];
}
function SubType(){
//继承了父类
SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");//red blue green black
alert(instance1.colors);
var instance2 = new SubType();
alert(instance2.colors);//red blue green
//传递参数
function SuperType(name){
this.name = name;
}
function SubType(){
//继承了父类,同时还传递了参数
SuperType.call(this,"Tom");
this.age = 29;
}
var instance1 = new SubType();
alert(instance1.name);//Tom
alert(instance1.age);//29
组合继承避免了原型链和借用构造函数的缺陷,融合了他们的有点,成为JS中最常用的继承模式。
而且instanceof和isPrototypeOf()也能够识别基于组合继承创建的对象
//组合继承(将原型链和借用构造函数的技术组合到一块)
function SuperType(name){
this.name = name;
this.colors = ["red","bule","green"];
}
SuperType.prototype.sayName = function(){
console.log(this.name);
};
function SubType(name,age){
//继承属性
SuperType.call(this,name);
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function(){
console.log(this.age);
};
//实例1
var instance1 = new SubType("Nicholas",29);
instance1.colors.push("black");
console.log(instance1.colors);//"red","bule","green","black"
instance1.sayName();//"Nicholas"
instance1.sayAge();//29
//实例2
var instance2 = new SubType("Greg",27);
console.log(instance2.colors);//"red","bule","green"
instance2.sayName();//"Greg"
instance2.sayAge();//27
//原型式继承
function object(o){
function F(){}
F.prototype = o;
return new F();
}
var person = {
name:"Tom",
friends:["Shelby","Court","Van"]
};
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
console.log(person.friends);//"Shelby","Court","Van","Rob","Barbie"
//寄生式继承
寄生组合继承
所谓寄生组合继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。其背后的基本思路是:不必为了指定子类型的原型而调用超类的构造函数,我们所需要的无非就是超类原型的一个副本而已。
function object(o){
function F(){}
F.prototype = o;
return new F();
}
function inheritPrototype(subType,superType){
var prototype = object(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(Submit,SuperType);
SubType.prototype.sayAge = function(){
alert(this.age);
}