javascript 继承

原型、构造函数、实例的关系:

每一个构造函数都有一个原型对象,每个原型对象都有一个指向构造函数的指针,实例包含一个指向原型对象的指针。

将一个原型对象 = 另一个对象的实例,那么此时的原型对象将包含一个指向另一个原型对象的指针,另一个原型包含一个指向另一个构造函数的指针。

  • 原型链继承:

实现方式将父类的实例赋值给子类的原型,即让子类的原型指向父类的原型,且父类的原型的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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值