JavaScript高等程序设计进修笔记之继续形式

原型链

JavaScript的继续重要依托原型链来完成的。我们晓得,组织函数,原型,和实例之间的关联:每一个组织函数都有一个原型对象,原型对象都包括一个指向组织函数的指针,而实例都包括一个原型对象的指针。

完成原型链的体式格局以下

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

function  SubType(){
    this.subpropertype=false;
}
//让原型对象称为另一个组织函数的实例
SubType.prototype=new SuperType();

SubType.prototype.getSubValue=function(){
    return this.subpropertype;
};
var  instance=new SubType();
alert(instance.getSuperValue());//true
//这个实例继续了SuperType.prototype的constructor属性?
alert(instance.constructor==SuperType);//true

上述代码继续是经由历程SubType.prototype=new SuperType();来完成,建立SuperType的实例,并将该实例赋给SubType.prototype

继续完成的实质是重写原型对象,代之以一个新范例的实例。

下图为组织函数,实例以及原型之间的关联图:

图片形貌

原型链顶端:一切援用范例都默许继续Object,所以,一切函数的默许原型都是Object的实例,默许原型都邑包括一个内部指针[[prototype]],指向Object.prototype。

原型链瑕玷

  1. 实例属性变成原型属性


function  SuperType(){
    this.color=["red","green","blue"];
}
function  SubType(){

}
SubType.prototype = new SuperType();

var instance1 = new SubType();
instance1.color.push("black");
alert(instance1.color);//"red,green,blue,black"

var instance2 = new SubType();
alert(instance2.color);//"red,green,blue,black"

这个题目素昧平生,恰是原型形式建立对象时因为同享援用范例属性,致使牵一发起满身的题目。

  1. 在建立子范例时,不能向超范例的组织函数通报参数。

所以,零丁运用原型链状况较少。

借用组织函数

针对原型链的第一个题目,我们可采用借用组织函数的手艺来处理。基本思想就是在子范例组织函数的内部挪用超范例组织函数。看例子:

function  SuperType(){
    this.color=["red","green","blue"];
}
function  SubType(){
    //继续自SuperType
    SuperType.call(this);
}
var instance1 = new SubType();
instance1.color.push("black");
alert(instance1.color);//"red,green,blue,black"

var instance2 = new SubType();
alert(instance2.color);//"red,green,blue"

在新建立的SubType子范例的实例中挪用SuperType超范例组织函数,就能够在新的实例对象上实行SuperType()函数中定义的一切对象初始化代码。题目不就处理了吗!
然则,这类形式的瑕玷是在超范例中定义的要领,对子范例是不可见的,没法完成同享要领。
所以,这类要领也不经常使用。

组合继续

组合上述两种要领就是组合继续。用原型链完成对原型属性和要领的继续,用借用组织函数手艺来完成实例属性的继续。无疑,集二者之大成,这才是最经常使用的继续形式。看:

function  SuperType(){
    this.name=name;
    this.color=["red","green","blue"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
}
function  SubType(name,age){
    //继续了SuperType
    SuperType.call(this,name);
    //本身又增加了一个
    this.age = age;
}
//构建原型链
SubType.prototype = new SuperType();
//重写SubType.prototype的constructor属性,指向本身的组织函数SubType
SubType.prototype.constructor=SubType;
//原型要领,被实例们同享
SubType.prototype.sayAge = function(){
    alert(this.age);
}

var instance1 = new SubType("Nichola",29);
instance1.color.push("black");
alert(instance1.color);//"red,green,blue,black"
instance1.sayName();//"Nichola"
instance1.sayAge();//29

var instance2 = new SubType("Grey",24);
alert(instance2.color);//"red,green,blue"
instance2.sayAge();//24
instance2.sayName();//"Grey"

这个计划已看似perfect了。然则,背面再说。

原型式继续

借助原型能够基于已有的对象建立新的对象,没必要因而建立自定义范例。

function object(o){     //返回一个对象以传入对象为原型
    function F(){}
    F.prototype = o;
    return new F();
}

var person ={
    name:"Nichola",
    friends:["Shelly","Court","Van"]
};
var person1 = object(person);
person1.name = "Grey";
person1.friends.push("Rob");

var person2 = object(person);
person2.name = "Linda";
person2.friends.push("Barble");

alert(person.friends);//"Shelly,Court,Van,Grey,Barble"

运用场所:需求简朴,只需要让新对象与已有对象坚持类似。长处,没必要建立组织函数,瑕玷,包括援用范例值的属性一直同享响应的值。
Object.create()恰是为完成这类形式降生。

寄生式继续

与原型式继续类似,也是基于某个对象或某些信息建立对象,然后加强对象,末了返回对象。完成要领:建立一个仅用于封装继续历程的函数,该函数在内部以某种体式格局来加强对象,末了返回这个对象。看!


function createAnother(original){
    var clone = object(original);//经由历程挪用函数建立对象
    clone.sayHi= function (){    //加强对象
        alert("Hi");
    };
    return clone;//返回对象
}
//能够返回新对象的函数
function object(o){
    function F(){}
    F.prototype = o;
    return new F();
}

var person ={
    name:"Nichola",
    friends:["Shelly","Court","Van"]
};

var anotherPerson = createAnother(person);
anotherPerson.sayHi();//"Hi"

这类继续形式实用的场所:任何返回新对象的函数都能够。瑕玷是不能做到函数复用。

寄生组合式继续

上面说到组合继续也有瑕玷,就是不管在何种状况下,都邑挪用两次超范例组织函数,一次是在建立子范例原型时,另有一次是在子范例组织函数内部。
这类形式集中了寄生式和组合式继续的长处。

function  SuperType(){
    this.name=name;
    this.color=["red","green","blue"];
}
function  SubType(){
    //第二次挪用SuperType()
    SuperType.call(this,name);
 
    this.age = age;
}
//第一次挪用SuperType()
SubType.prototype = new SuperType();

SubType.prototype.constructor=SubType;

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

var instance1 = new SubType("Nichola",29);

第一次挪用SuperType():给SubType.prototype写入两个属性name,color
第二次挪用SuperType():给instance1写入两个属性name,color
实例对象instance1上的两个属性就屏障了其原型对象SubType.prototype的两个同名属性。所以,组合形式的瑕玷就是在SubType.prototype上建立没必要要的反复的属性。
寄生组合式继续基本形式:

function  inheritPrototype(SubType,SuperType){
    var prototype = object(superType.prototype);//建立对象
    prototype.constructor = SubType;//加强对象
    SubType.prototype = prototype;//制订对象
}

起首,建立超范例的一个副本;
其次,为副本增加constructor属性,使其指向子范例组织函数;
末了,将副本赋值给子范例原型。

function  SuperType(){
    this.name=name;
    this.color=["red","green","blue"];
}
function  SubType(){
    SuperType.call(this.name);
    this.age = age;
}
function  inheritPrototype(SubType,SuperType){
    var prototype = object(superType.prototype);//建立对象
    prototype.constructor = SubType;//加强对象
    SubType.prototype = prototype;//制订对象
}
SubType.prototype.sayAge = function(){
    alert(this.age);
}

var instance1 = new SubType("Nichola",29);

借用组织函数来继续实例属性,运用寄生式继续来继续超范例的原型,然后再将效果赋给子范例原型。如许既能够继续超范例的实例属性,也可继续超范例原型中的原型属性。这是最优解。

    原文作者:kongwsh
    原文地址: https://segmentfault.com/a/1190000007468947
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞