国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

讀《javaScript高級(jí)程序設(shè)計(jì)-第6章》之繼承

villainhr / 1078人閱讀

摘要:此時(shí)的原型對(duì)象包括一個(gè)指向另一個(gè)原型的指針,相應(yīng)的,另一個(gè)原型中的指向另一個(gè)構(gòu)造函數(shù)。這種關(guān)系層層遞進(jìn),就通過一個(gè)原型對(duì)象鏈接另一個(gè)構(gòu)造函數(shù)的原型對(duì)象的方式實(shí)現(xiàn)了繼承。

讀這篇之前,最好是已讀過我前面的關(guān)于對(duì)象的理解和封裝類的筆記。
第6章我一共寫了3篇總結(jié),下面是相關(guān)鏈接:
讀《javaScript高級(jí)程序設(shè)計(jì)-第6章》之理解對(duì)象
讀《javaScript高級(jí)程序設(shè)計(jì)-第6章》之封裝類

一、原型鏈

原型鏈最簡(jiǎn)單的理解就是:原型對(duì)象指向另一個(gè)構(gòu)造函數(shù)的實(shí)例。此時(shí)的原型對(duì)象包括一個(gè)指向另一個(gè)原型的指針,相應(yīng)的,另一個(gè)原型中的constructor指向另一個(gè)構(gòu)造函數(shù)。這種關(guān)系層層遞進(jìn),就通過一個(gè)原型對(duì)象鏈接另一個(gè)構(gòu)造函數(shù)的原型對(duì)象的方式實(shí)現(xiàn)了繼承。
下面用代碼和圖來詳細(xì)分析一下原型鏈中的各種關(guān)系:

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

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

function SubType(){
??? this.subproperty = false;
}

//inherit from SuperType
SubType.prototype = new SuperType();

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

var instance = new SubType();
alert(instance.getSuperValue());?? //true
alert(instance.getSubValue());?? //false
alert(instance instanceof Object);????? //true
alert(instance instanceof SuperType);?? //true
alert(instance instanceof SubType);???? //true

alert(Object.prototype.isPrototypeOf(instance));??? //true
alert(SuperType.prototype.isPrototypeOf(instance)); //true
alert(SubType.prototype.isPrototypeOf(instance));?? //true
console.log(new SuperType());
console.log(instance);

下圖是上面代碼中打印出來的new SuperType()和instance的分析:

從上面的分析我們看到的原型鏈:
SubType的原型里有指向SuperType的原型的指針,SuperType的原型里有指向Object的原型的指針。
也可以看紅皮書里的圖:

訪問屬性的搜索過程:

當(dāng)以讀取模式訪問一個(gè)構(gòu)造函數(shù)(SubType)的實(shí)例的屬性時(shí),首先會(huì)在實(shí)例中搜索實(shí)例屬性。如果沒找到該屬性,則會(huì)繼續(xù)搜索實(shí)例的原型;SubType繼承了SuperType,那么實(shí)例的原型是另一個(gè)構(gòu)造函數(shù)(SuperType)的實(shí)例,搜索實(shí)例的原型也就是在SuperType的實(shí)例中搜索該屬性,沒找到繼續(xù)搜索SuperType的原型;SuperType繼承了Object,以此遞進(jìn),一層層搜索,直到找到或者搜到了原型鏈的末端停下來。

判斷原型和實(shí)例的關(guān)系

(1)instanceof
實(shí)例的原型鏈中出現(xiàn)過待檢測(cè)的構(gòu)造函數(shù),就會(huì)返回true

alert(instance instanceof Object);????? //true
alert(instance instanceof SuperType);?? //true
alert(instance instanceof SubType);???? //true

(2)isPrototypeOf()方法
待檢測(cè)對(duì)象出現(xiàn)在instance的原型鏈中,就會(huì)返回true

alert(Object.prototype.isPrototypeOf(instance));??? //true
alert(SuperType.prototype.isPrototypeOf(instance)); //true
alert(SubType.prototype.isPrototypeOf(instance));?? //true

注意事項(xiàng)

(1)給原型添加方法的代碼一定要放在替換原型的語句之后。也就是

SubType.prototype = new SuperType();這句代碼一定要先寫,在寫下面的代碼
//new method
SubType.prototype.getSubValue = function (){
??? return this.subproperty;
};

//override existing method
SubType.prototype.getSuperValue = function (){
??? return false;
};

(2)在通過原型鏈實(shí)現(xiàn)繼承時(shí),不能使用對(duì)象字面量為原型添加屬性,因?yàn)檫@會(huì)重寫原型鏈(具體請(qǐng)看理解對(duì)象篇里的一、創(chuàng)建對(duì)象)。
如下:

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

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

function SubType(){
??? this.subproperty = false;
}

//繼承了 SuperType
SubType.prototype = new SuperType();

//使用字面量添加新方法,會(huì)導(dǎo)致上一行代碼無效
SubType.prototype = {
??? getSubValue : function (){
??????? return this.subproperty;
??? },

??? someOtherMethod : function (){
??????? return false;
??? }
};

var instance = new SubType();
alert(instance.getSuperValue());?? //error!

其實(shí)這兩個(gè)注意事項(xiàng),只要你明白了(理解對(duì)象篇里的一、創(chuàng)建對(duì)象)后,根本不需要解釋。

原型鏈的問題

(1)沒有辦法在不影響所有對(duì)象實(shí)例的情況下,給超類型的構(gòu)造函數(shù)傳遞參數(shù)。
(2)在另一篇筆記封裝類原型模式中提到過,原型中的屬性是被共享的,但如果屬性的值時(shí)引用類型,會(huì)有問題的。而在繼承時(shí),原型實(shí)際上會(huì)是另一個(gè)類型的實(shí)例(這個(gè)實(shí)例包含引用類型值的實(shí)例屬性),那么原先的這個(gè)實(shí)例的實(shí)例屬性就會(huì)成為現(xiàn)在的原型屬性了,就會(huì)出現(xiàn)同樣的問題了。共享了引用類型值的屬性。

二、借用構(gòu)造函數(shù)

直接上代碼吧:

function SuperType(name){
??? this.name = name;
}

function SubType(){?
??? //繼承了 SuperType ,同時(shí)還傳遞了參數(shù)
??? SuperType.call(this, "Nicholas");
???
??? //實(shí)例屬性
??? this.age = 29;
}

var instance = new SubType();
alert(instance.name);??? //"Nicholas";
alert(instance.age);???? //29

如上寫法就解決了原型鏈里的兩個(gè)問題了,為什么呢?請(qǐng)看下面的講解:
SuperType,如果你用new調(diào)用它是構(gòu)造函數(shù),但你不用new,它就是個(gè)普通函數(shù)。SuperType.call(this, "Nicholas");不但傳遞了參數(shù),還綁定了子類的作用域,就相當(dāng)于SuperType方法在幫助定義子類的實(shí)例屬性。也就是說,即使SuperType的中定義的屬性里有引用類型值,也不會(huì)成為子類SubType的原型屬性,仍然時(shí)實(shí)例屬性。我們要時(shí)刻記住實(shí)例屬性是每個(gè)實(shí)例所私有的,而原型屬性是會(huì)被所有實(shí)例所共享的。

當(dāng)然這也寫也不完美,問題顯而易見,和構(gòu)造函數(shù)模式同樣的問題。

三、組合繼承

組合繼承,就像是封裝類里的把構(gòu)造函數(shù)模式和原型模式組合使用是一樣的。這里是把原型鏈和借用構(gòu)造函數(shù)相組合。
簡(jiǎn)單來說就是:使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,通過借用構(gòu)造函數(shù)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承(父類的實(shí)例屬性變成子類的實(shí)例屬性)。
還是上代碼吧:

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;
}

SubType.prototype = new SuperType();
SubType.prototype.sayAge = function(){
??? alert(this.age);
};
var instance1 = new SubType("Nicholas",29);

instance1.colors.push("black");
alert(instance1.colors);?//"red,blue,green,black"
instance1.sayName();????? //"Nicholas";
instance1.sayAge();?????? //29

var instance2 = new SubType("Greg", 27);

alert(instance2.colors);? //"red,blue,green"
instance2.sayName();????? //"Greg";
instance2.sayAge();?????? //27

解釋:
下圖是instance1的打印

我們可以看到instance1具有了父類SuperType的實(shí)例屬性name 、colors,但是子類的原型是父類的實(shí)例,所以原型中仍存在父類的實(shí)例屬性,但是子類已經(jīng)有了同樣的實(shí)例屬性name和colors,所以子類原型中的這兩個(gè)屬性就被屏蔽了。從子類訪問它的name和colors屬性只會(huì)訪問到它的實(shí)例屬性。

組合繼承是javaScript中最常用的繼承模式。而且instance和isPrototypeOf()也能夠用于識(shí)別給予組合繼承創(chuàng)建的對(duì)象類型。

四、原型式繼承

感興趣可以了解一下。
原型鏈中,我們是讓原型對(duì)象指向一個(gè)構(gòu)造函數(shù)的實(shí)例,這個(gè)實(shí)例本質(zhì)上就是一個(gè)對(duì)象。原型式繼承就是讓原型對(duì)象指向一個(gè)已有的對(duì)象,不必創(chuàng)建自定義類型。如下:

function object(o){
??? function F(){}
??? F.prototype = o;
??? return new F();
}
var person = {
??? name: "Nicholas",
??? friends: ["Shelby", "Court", "Van"]
};

var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");

var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
console.log(person.friends);?? //"Shelby,Court,Van,Rob,Barbie”

大家還記得原型模式嗎。我的理解:這就是一個(gè)原型模式,區(qū)別是object這個(gè)方法就相當(dāng)于一個(gè)工廠,你傳給它一個(gè)對(duì)象,它就給你一個(gè)原型是這個(gè)對(duì)象的實(shí)例。這個(gè)實(shí)例就會(huì)相應(yīng)的繼承到了你傳給它的那個(gè)對(duì)象的屬性。
當(dāng)然你也可以不用自己寫上面的object這個(gè)方法,因?yàn)镋S5提供了,而且更規(guī)范。ES5中新增了Object.create()方法規(guī)范化了原型式繼承。這個(gè)方法接受兩個(gè)參數(shù):一個(gè)是用做新對(duì)象原型的對(duì)象和(可選)一個(gè)為新對(duì)象定義額外屬性的對(duì)象(或者說是定義新對(duì)象的實(shí)例屬性的對(duì)象,這個(gè)參數(shù)和defineProperties()方法的第二個(gè)參數(shù)格式相同:每個(gè)屬性都是通過自己的描述符定義的)。
上代碼:

var person = {
??? name: "Nicholas",
??? friends: ["Shelby", "Court", "Van"]
};
??????????????????
var anotherPerson = Object.create(person, {
??? name: {
??????? value: "Greg"
??? }
});
console.log(anotherPerson);

打印結(jié)果圖:

從上圖可以看到第二個(gè)參數(shù)定義的name屬性是新對(duì)象的實(shí)例屬性,它會(huì)屏蔽掉它的原型屬性里的同名屬性name。簡(jiǎn)單來說,Object.create就是用原型模式創(chuàng)建新對(duì)象的一個(gè)工廠,第一個(gè)參數(shù)定義了原型屬性,第二個(gè)參數(shù)定義了實(shí)例屬性。

五、寄生式繼承

這一小節(jié),感興趣了解一下。

六、寄生組合式繼承

前面說過,組合繼承是js里最常用的繼承模式,但是它并不完美。問題是:調(diào)用了兩次超類SuperType的構(gòu)造函數(shù),子類創(chuàng)建了一部分多余的屬性(這部分屬性是超類的實(shí)例屬性,在子類的實(shí)例屬性里存在并有用,但在子類的原型中也存在且沒用)。寄生組合式繼承就是解決這個(gè)問題的。
上代碼:

function object(o){
??? function F(){}
??? F.prototype = o;
??? return new F();
}

function inheritPrototype(subType, superType){
??? var prototype = object(superType.prototype);?? //create object???         
    prototype.constructor = subType;?????????//augment object??? 
    subType.prototype = prototype;???????? //assign object
}
???????????????????????
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;
}

inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
??? alert(this.age);
};

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

instance1.colors.push("black");
alert(instance1.colors);?//"red,blue,green,black"
instance1.sayName();????? //"Nicholas";
instance1.sayAge();?????? //29

var instance2 = new SubType("Greg", 27);

alert(instance2.colors);? //"red,blue,green"
instance2.sayName();????? //"Greg";
instance2.sayAge();?????? //27

console.log(instance1);
console.log(SuperType.prototype)

代碼運(yùn)行打印結(jié)果圖:

從圖中可以看到instance1(子類實(shí)例)的原型里已經(jīng)沒有了超類的實(shí)例屬性name、colors。而且代碼中只運(yùn)行了一次超類構(gòu)造函數(shù)。怎么做到的呢?請(qǐng)看下面的解釋:
我們先看這段代碼:

function inheritPrototype(subType, superType){
??? var prototype = object(superType.prototype);?? //create object
??? prototype.constructor = subType;?????????????? //augment object
??? subType.prototype = prototype;???????????????? //assign object
}

subType的原型還是指向了一個(gè)對(duì)象,這個(gè)對(duì)象是什么呢?object這個(gè)方法返回的對(duì)象,這個(gè)對(duì)象是一個(gè)構(gòu)造函數(shù)是空的,原型指向超類原型的實(shí)例。什么意思呢?就是說subType的原型還是一個(gè)構(gòu)造函數(shù)的實(shí)例,但不是超類SuperType的實(shí)例,而是一個(gè)新建的臨時(shí)的空的構(gòu)造函數(shù)F的實(shí)例。看代碼:

function object(o){
??? function F(){}
??? F.prototype = o;
??? return new F();
}

這個(gè)臨時(shí)的構(gòu)造函數(shù)F具有和超類SuperType一樣的原型。那么這個(gè)時(shí)候的子類的原型中就只有F的實(shí)例屬性和原型,而F的實(shí)例屬性是空的,就只有F的原型,F(xiàn)的原型就是超類SuperType的原型。這樣子類的實(shí)例屬性還是繼承了超類的實(shí)例屬性,而子類的原型屬性只繼承了超類的原型。完美,就這樣。

啰嗦一句我對(duì)面向?qū)ο蟪绦蛟O(shè)計(jì)的理解,面向?qū)ο蟪绦蛟O(shè)計(jì)就是一直在說如何使用對(duì)象。其實(shí),只要結(jié)果符合你的預(yù)期,對(duì)象真的是想怎么使用就怎么使用,不一定非得像書中說的什么各種模式的。當(dāng)然書中的這么多種模式方法的介紹可以了解一下(但是構(gòu)造函數(shù)模式、原型模式。以及繼承里的原型鏈、借用構(gòu)造函數(shù)。還包括它們的組合使用還是需要認(rèn)真研讀,深刻理解的。再順便說一句,繼承里的原型鏈、借用構(gòu)造函數(shù)可以看作是原型模式和構(gòu)造函數(shù)模式的進(jìn)化),可以加深自己對(duì)對(duì)象的理解,有助于你花式使用對(duì)象的方法。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/89309.html

相關(guān)文章

  • javaScript高級(jí)程序設(shè)計(jì)6理解對(duì)象

    摘要:把對(duì)象定義為無序?qū)傩缘募希鋵傩钥梢园局祵?duì)象或函數(shù)。接受兩個(gè)參數(shù)屬性所在的對(duì)象和要讀取其特性的屬性名返回的時(shí)其特性的對(duì)象例如讀高級(jí)程序設(shè)計(jì)這本書的第章面向?qū)ο蟮某绦蛟O(shè)計(jì),我做了篇筆記。這是第一篇,后面還有兩篇,分別是封裝類和繼承。 ECMA-262把對(duì)象定義為:無序?qū)傩缘募?,其屬性可以包含基本值、?duì)象或函數(shù)。所以,我們可以理解對(duì)象就是名值對(duì)的集合,名就是對(duì)象的每個(gè)屬性的名字,...

    KoreyLee 評(píng)論0 收藏0
  • javaScript高級(jí)程序設(shè)計(jì)6封裝類

    摘要:創(chuàng)建構(gòu)造函數(shù)后,其原型對(duì)象默認(rèn)只會(huì)取得屬性至于其他的方法都是從繼承來的。上圖展示了構(gòu)造函數(shù)的原型對(duì)象和現(xiàn)有的兩個(gè)實(shí)例之間的關(guān)系。所有原生的引用類型都在其構(gòu)造函數(shù)的原型上定義了方法。 第6章我一共寫了3篇總結(jié),下面是相關(guān)鏈接:讀《javaScript高級(jí)程序設(shè)計(jì)-第6章》之理解對(duì)象讀《javaScript高級(jí)程序設(shè)計(jì)-第6章》之繼承 工廠模式 所謂的工廠模式就是,把創(chuàng)建具體對(duì)象的過程抽象...

    seal_de 評(píng)論0 收藏0
  • 如何閱JavaScript高級(jí)程序設(shè)計(jì)》(一)

    摘要:題外話最近在看高級(jí)程序設(shè)計(jì)這本書,面對(duì)著多頁的厚書籍,心里有點(diǎn)壓力,所以我決定梳理一下。。全局環(huán)境的關(guān)閉是頁面關(guān)閉或者瀏覽器關(guān)閉,而局部環(huán)境的關(guān)閉是指函數(shù)結(jié)束。數(shù)值范圍最大和最小的范圍是超出范圍的數(shù)字如何表示是一個(gè)特殊的值。 題外話 最近在看《JavaScript高級(jí)程序設(shè)計(jì)》這本書,面對(duì)著700多頁的厚書籍,心里有點(diǎn)壓力,所以我決定梳理一下。。探究一下到底怎么讀這本書。本書的內(nèi)容好像...

    chadLi 評(píng)論0 收藏0
  • 如何閱JavaScript高級(jí)程序設(shè)計(jì)》(一)

    摘要:題外話最近在看高級(jí)程序設(shè)計(jì)這本書,面對(duì)著多頁的厚書籍,心里有點(diǎn)壓力,所以我決定梳理一下。。全局環(huán)境的關(guān)閉是頁面關(guān)閉或者瀏覽器關(guān)閉,而局部環(huán)境的關(guān)閉是指函數(shù)結(jié)束。數(shù)值范圍最大和最小的范圍是超出范圍的數(shù)字如何表示是一個(gè)特殊的值。 題外話 最近在看《JavaScript高級(jí)程序設(shè)計(jì)》這本書,面對(duì)著700多頁的厚書籍,心里有點(diǎn)壓力,所以我決定梳理一下。。探究一下到底怎么讀這本書。本書的內(nèi)容好像...

    jubincn 評(píng)論0 收藏0
  • 如何閱JavaScript高級(jí)程序設(shè)計(jì)》(一)

    摘要:題外話最近在看高級(jí)程序設(shè)計(jì)這本書,面對(duì)著多頁的厚書籍,心里有點(diǎn)壓力,所以我決定梳理一下。。全局環(huán)境的關(guān)閉是頁面關(guān)閉或者瀏覽器關(guān)閉,而局部環(huán)境的關(guān)閉是指函數(shù)結(jié)束。數(shù)值范圍最大和最小的范圍是超出范圍的數(shù)字如何表示是一個(gè)特殊的值。 題外話 最近在看《JavaScript高級(jí)程序設(shè)計(jì)》這本書,面對(duì)著700多頁的厚書籍,心里有點(diǎn)壓力,所以我決定梳理一下。。探究一下到底怎么讀這本書。本書的內(nèi)容好像...

    libin19890520 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<