Javascript学习笔记2 继承 原型链

原型链

使某个原型对象成为另一个类型的实例,该原型对象将包含一个指向另一个原型的指针,如此层层递进,就构成了实例与原型的链条

function SuperType(){
    this.property = true;
}

SuperType.prototype.getSuperValue = function(){
    return this.property;
};

function SubType(){
    this.subproperty = false;
}
//继承
SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function(){
    return this.subproperty;
};

var instance = new SubType();
alert(instance.getSuperValue()); //true
  • 当子类型需要覆盖超类型中的某个方法或添加超类型没有的方法时,给原型添加的方法的代码一定要放在替换原型的语句之后
  • 通过原型链实现继承时,不能使用对象字面量的方式创建原型方法,否则会重写原型,从而切断了原型链
  • 不足包含引用类型值的原型会被所有实例共享

关系如下:
这里写图片描述
原型搜索机制:首先在实例中搜索该属性,如果没有找到,则会继续在实例的原型中搜索,若还未找到,则在原型链实现继承的情况下,会继续向上搜索原型对象的原型对象,直达搜索到原型链的末端。

所有引用类型都默认继承了Oject对象,因此所有默认原型的__proto__属性都会指向Object.prototype。关于__proto__、prototype、constructor的关系,以及js中所有对象都继承于Object这点可以用这张图说明
这里写图片描述

  • 实例对象是构造函数创建的,实例对象的__proto__属性指向其原型对象,构造函数的prototype指向原型对象,原型对象的constructor指向构造函数
  • 构造函数也是实例对象,其是由function这个构造函数创建的,同时function的原型对象(function.prototype)也是对象,其是由Object这个构造函数创造的,原型对象是Object.prototype。换句话说,即function.prototype.__proto__等于Object.prototype

更详细的讲解,请参考这篇博客,这张图也是引用他的 https://www.cnblogs.com/xiaohuochai/p/5721552.html

借用构造函数

为解决原型链中引用值类型共享及参数传递问题,在子类型的构造函数的内部调用超类型的构造函数

function SuperTypename){
    this.name = name;
}

function SubType(){
    SuperType.call(this,"zjw");   //执行超类的构造函数,传入SubType的环境对象和参数,
                                  //执行代码后,name属性就创建在了SubType的实例上
    this.age = 28;
}

var instance = new SubType();
alert(instance.name)  //"zjw"
alert(instance.age)  //28
  • 不足:构造函数无法解决函数复用问题,每次都要重新创造实例方法

组合继承

原型链和借用构造函数组合到一块,使用原型链实现对原型属性和方法的继承,而构造函数实现对实例属性的继承

function SuperTypename){                  //超类的构造函数
    this.name = name;
    this.colors = ["red","blue","green"];
}

SuperType.prototype.sayName = function(){   //给超类的原型添加方法
    alert(this.name);
};

function SubType(name,age){   //子类的构造函数
    SuperType.call(this,name);  //调用超类的构造函数,使每个实例都具有colors属性的副本
                                //从而没有直接继承超类的引用型属性
    this.age = age;
}

SubType.prototype = new SuperType();   //继承超类
SubType.prototype.constructor = SubType;

SubType.prototype.sayAge = function(){   //给子类的原型添加方法
    alert(this.age);
};

var instance1 = new SubType("zjw",29);   //创建子类型
instance1.colors.push("black");
alert(instance1.colors);   //"red","blue","green","black"
instance1.sayName();   //"zjw"
instance1.sayAge();   //29

var instance2 = new SubType("bob",27);
alert(instance1.colors);   //"red","blue","green"
instance1.sayName();   //"bob"
instance1.sayAge();   //27

原型式继承

基于已有对象创建新对象(浅复制,引用类型属性仍然共享)
直接使用Object.create()方法,接受两个参数:要复制的对象和新添属性的对象

var anotherPerson = Object.create(Person,{
    name:{
        value:"zjw"
    }
});

寄生式继承

创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回对象,与工厂模式类似

function createAnother(o){
    var clone = object(o)  //创建新对象

    clone.sayHi = function(){  //添加新方法
        alert("hi");
    }
    return clone;   //返回新对象
}
var person = {name:"zjw"};
var anotherPerson = createAnother(person);
anotherPerson.sayHi();   //hi
  • 跟构造函数一样不能做到函数复用

寄生组合式继承

解决传统的组合继承调用两次超类型构造函数问题,该方法用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型

function inheritProperty(SubType,SuperType){
    var prototype = object(SuperType.prototype);  //创建超类原型的副本
    SubType.prototype = prototype;                //继承超类副本
    SubType.prototype.constructor = SubType;      //弥补重写原型而丢失的constructor属性
}

function SuperTypename){                  //超类的构造函数
    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;
}

inheritProperty(SubType,SuperType);  //调用自定义的继承函数

SubType.prototype.sayAge = function(){ 
    alert(this.age);
};
  • 其避免了SubType.prototype = new SuperType();调用超类的构造函数
  • 该种继承模式最有效,结合了组合继承和寄生式继承的优点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值