原型、构造函数、实例的关系:
每一个构造函数都有一个原型对象,每个原型对象都有一个指向构造函数的指针,实例包含一个指向原型对象的指针。
将一个原型对象 = 另一个对象的实例,那么此时的原型对象将包含一个指向另一个原型对象的指针,另一个原型包含一个指向另一个构造函数的指针。
-
原型链继承:
实现方式将父类的实例赋值给子类的原型,即让子类的原型指向父类的原型,且父类的原型的constructor属性指向父类构造函数
缺点:(1)引用类型的原型属性会被共享;(2)在创建子类时,不能像超类型的构造函数中传递参数
//原型继承
function SuperType(){
this.color = ['red','gray','orange'];
}
function SubType(){
}
SubType.prototype = new SuperType();
console.log(SubType.prototype.constructor);//[Function: SuperType]
var instance1 = new SubType();
instance1.color.push('yellow');
console.log(instance1.color);//[ 'red', 'gray', 'orange', 'yellow' ]
var instance2 = new SubType();
console.log(instance2.color);//[ 'red', 'gray', 'orange', 'yellow' ]
-
构造函数继承
实现方式:在子类构造函数中,调用父类构造函数(解决引用类型属性)
优势:传递参数:在子类构造中给父类构造传递参数 缺点:方法都在构造函数中定义,函数复用难以达到,不满足继承的封装性
function SuperType(age){
this.color = ['red','gray','orange'];
this.age = age;
}
function SubType(age){
SuperType.call(this,age);
//此处添加子类特有属性
}
var instance1 = new SubType(23);
console.log(SubType.prototype.constructor);//[Function:SubType]
instance1.color.shift();//去头
console.log(instance1.color)
console.log(instance1.age);
var instance2 = new SubType(28);
console.log(SubType.prototype.constructor);//[Function:SubType]
console.log(instance2.color)
console.log(instance2.age);
-
组合继承
结合构造函数继承中引用值属性不共享的优点 和 原型链继承中方法复用的优点,提出了组合继承。
下面的代码,不是SubType的constructor被重写,而是将SubType的原型指向了SuperType的原型,此时SuperType原型的constructor属性指向的SuperType构造函数。即SubType.prototye.constructor = SuperType.
SubType.prototype = new SuperType();
由于SubType.prototye.constructor = SuperType. 违背了原型继承的设计语意,所以将SubType.prototye.constructor指向了子类SubType的构造函数。
SubType.prototype.constructor = SubType;
//组合继承
// 超类型有name和colors、sayName(),子类型有age、sayAge
function SuperType(name){
this.name = name;
this.color =['green','red','yellow'];
}
SuperType.prototype.sayName = function(){
console.log(this.name);
}
function SubType(name,age){
//继承父类
SuperType.call(this,name);
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
//子类添加原型方法
console.log(SubType.prototype.constructor);//[Function: SuperType]
var instance1 = new SubType("lihua",23);
console.log(instance1 instanceof SubType);//true
console.log(instance1 instanceof SuperType);//true
//SubType原型的构造函数却是SuperType,这个就和原型"继承"的设计语义相违背,所以重新设置,使SubType原型的构造器对象指向了SubType
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){//增加子类方法,解决构造函数方法多次创建的问题,所以将方法定义到原型上。
console.log(this.age);
}
instance1.color.push("black");
console.log(instance1.color);//[ 'green', 'red', 'yellow', 'black' ]
instance1.sayName();//lihua
instance1.sayAge();//23
-
原型继承
将传入的对象作为返回对象的原型,返回实例。引用属性共享 。工厂模式不需要new
// ES5规范化Object.create(对象,对象属性{name:"dd"})原型继承
//原型继承,实则是浅复制
var person = {
name:"Nicholas",
friends:["A","B","C"]
}
function object(o){
function F(){};
F.prototype = o;
return new F();
}
var newobject = object(person);//person和object共享所有属性
newobject.age = 24;
newobject.friends.push("D");
console.log(newobject.age);//[ 'A', 'B', 'C', 'D' ]
console.log(person.friends);//[ 'A', 'B', 'C', 'D' ]
console.log(newobject.name);//Nicholas
-
寄生示继承
在原生继承的基础上,将添加新方法等增强方式,封装成函数。新的对象为 creatperson(person)
但是由于不能做到函数复用而降低效率。
var person = {
name:"Nicholas",
friends:["A","B","C"]
}
function object(o){
function F(){};
F.prototype = o;
return new F();
}
function creatPerson(o){
var clone = object(o);
clone.sayHi = function(){
console.log("hi");
}
return clone;
}
var newobject = creatPerson(person);//person和object共享所有属性
newobject.sayHi();//hi
newobject.age = 24;
newobject.friends.push("D");
console.log(newobject.age);//24
console.log(person.friends);//[ 'A', 'B', 'C', 'D' ]
console.log(newobject.name);//Nicholas
- 寄生组合继承
组合继承:无论什么情况都会调用两次超类型构造函数:一次是创建子类原型时new 父类();第二次是在子类构造函数内部。
这就会导致:有两组父类的实例属性,一组在子类的实例上,一组在子类的原型中。
寄生组合继承:不必为了子类性的原型调用父类的构造函数。
function SuperType(name){
this.name = name;
this.color =['green','red','yellow'];
}
SuperType.prototype.sayName = function(){
console.log(this.name);
}
function SubType(name,age){
SuperType.call(this,name);
this.age = age;
}
function object(o){
function F(){};
F.prototype = o;
return new F();
}
function inheritPrototype(SuperType,SubType){
var proto = object(SuperType);//创建超类型的副本
proto.constructor = SubType;//增强对象
SubType.prototype.constructor = proto;//指定对象
}
inheritPrototype(SuperType,SubType);
var instance1 = new SubType("nick",23);
console.log(instance1.name);//nick
console.log(instance1 instanceof SubType);//true