您的位置:首页 > Web前端 > JavaScript

Javascript学习笔记2 继承 原型链

2018-03-13 18:07 633 查看

原型链

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

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 SuperType(name){
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 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);  //调用超类的构造函数,使每个实例都具有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 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;
}

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

SubType.prototype.sayAge = function(){
alert(this.age);
};


其避免了
SubType.prototype = new SuperType();
调用超类的构造函数

该种继承模式最有效,结合了组合继承和寄生式继承的优点
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: