深入了解javascript中的prototype與繼承
通常來(lái)說(shuō),javascript中的對(duì)象就是一個(gè)指向prototype的指針和一個(gè)自身的屬性列表。javascript創(chuàng)建對(duì)象時(shí)采用了寫(xiě)時(shí)復(fù)制的理念。
只有構(gòu)造器才具有prototype屬性,原型鏈繼承就是創(chuàng)建一個(gè)新的指針,指向構(gòu)造器的prototype屬性。
prototype屬性之所以特別,是因?yàn)閖avascript時(shí)讀取屬性時(shí)的遍歷機(jī)制決定的。本質(zhì)上它就是一個(gè)普通的指針。
構(gòu)造器包括:
1.Object
2.Function
3.Array
4.Date
5.String
下面我們來(lái)舉一些例子吧
<script>
//每個(gè)function都有一個(gè)默認(rèn)的屬性prototype,而這個(gè)prototype的constructor默認(rèn)指向這個(gè)函數(shù)
//注意Person.constructor 不等于 Person.prototype.constructor. Function實(shí)例自帶constructor屬性
function Person(name) {
this.name = name;
};
Person.prototype.getName = function() {
return this.name;
};
var p = new Person("ZhangSan");
console.log(Person.prototype.constructor === Person); // true
console.log(p.constructor === Person); // true ,這是因?yàn)閜本身不包含constructor屬性,所以這里其實(shí)調(diào)用的是Person.prototype.constructor
</script>
我們的目的是要表示
1.表明Person繼承自Animal
2. 表明p2是Person的實(shí)例
我們修改一下prototype屬性的指向,讓Person能獲取Animal中的prototype屬性中的方法。也就是Person繼承自Animal(人是野獸)
<script>
function Person(name) {
this.name = name;
};
Person.prototype.getName = function() {
return this.name;
};
var p1 = new Person("ZhangSan");
console.log(p.constructor === Person); // true
console.log(Person.prototype.constructor === Person); // true
function Animal(){ }
Person.prototype = new Animal();//之所以不采用Person.prototype = Animal.prototype,是因?yàn)閚ew 還有其他功能,最后總結(jié)。
var p2 = new Person("ZhangSan");
//(p2 -> Person.prototype -> Animal.prototype, 所以p2.constructor其實(shí)就是Animal.prototype.constructor)
console.log(p2.constructor === Person); // 輸出為false ,但我們的本意是要這里為true的,表明p2是Person的實(shí)例。此時(shí)目的1達(dá)到了,目的2沒(méi)達(dá)到。
</script>
但如果我們這么修正
Person.prototype = new Animal();
Person.prototype.constructor = Person;
這時(shí)p2.consturctor是對(duì)了,指向的是Person,表示p2是Person類(lèi)的實(shí)例,但是新問(wèn)題出現(xiàn)了。此時(shí)目的2達(dá)到了,目的1沒(méi)達(dá)到。
目的1和目的2此時(shí)互相矛盾,是因?yàn)榇藭r(shí)prototype表達(dá)了矛盾的兩個(gè)意思,
1表示父類(lèi)是誰(shuí)
2作為自己實(shí)例的原型來(lái)復(fù)制
因此我們不能直接使用prototype屬性來(lái)表示父類(lèi)是誰(shuí),而是用getPrototypeOf()方法來(lái)知道父類(lèi)是誰(shuí)。
Person.prototype = new Animal();
Person.prototype.constructor = Person;
var p2 = new Person("ZhangSan");
p2.constructor //顯示 function Person() {}
Object.getPrototypeOf(Person.prototype).constructor //顯示 function Animal() {}
就把這兩個(gè)概念給分開(kāi)了
最后總結(jié)一下:
當(dāng)代碼var p = new Person()執(zhí)行時(shí),new 做了如下幾件事情:
創(chuàng)建一個(gè)空白對(duì)象
創(chuàng)建一個(gè)指向Person.prototype的指針
將這個(gè)對(duì)象通過(guò)this關(guān)鍵字傳遞到構(gòu)造函數(shù)中并執(zhí)行構(gòu)造函數(shù)。
如果采用Person.prototype = Animal.prototype來(lái)表示Person繼承自Animal, instanceof方法也同樣會(huì)顯示p也是Animal的實(shí)例,返回為true.之所以不采用此方法,是因?yàn)橄旅鎯蓚€(gè)原因:
1.new 創(chuàng)建了一個(gè)新對(duì)象,這樣就避免了設(shè)置Person.prototype.constructor = Person 的時(shí)候也會(huì)導(dǎo)致Animal.prototype.constructor的值變?yōu)镻erson,而是動(dòng)態(tài)給這個(gè)新創(chuàng)建的對(duì)象一個(gè)constructor實(shí)例屬性,這樣實(shí)例上的屬性constructor就覆蓋了Animal.prototype.constructor,這樣Person.prototype.constructor和Animal.prototype.contructor就分開(kāi)了。
2.Animal自身的this對(duì)象的屬性沒(méi)辦法傳遞給Person
通過(guò)使用 hasOwnProperty()方法,什么時(shí)候訪問(wèn)的是實(shí)例屬性,什么時(shí)候訪問(wèn)的是原型屬性就 一清二楚了。
相關(guān)文章
淘寶網(wǎng)提供的國(guó)內(nèi)NPM鏡像簡(jiǎn)介和使用方法
我們以前介紹過(guò)cnpmjs.org,非常棒的npm國(guó)內(nèi)鏡像。由于其使用量越來(lái)越大,加上淘寶內(nèi)部也有很多項(xiàng)目使用 NodeJS,于是,淘寶正式基于 cnpmjs 推出了鏡像服務(wù)2014-04-04JavaScript中圓括號(hào)()和方括號(hào)[]的特殊用法疑問(wèn)解答
大家對(duì)JavaScript中圓括號(hào)() 和 方括號(hào)[] 的特殊用法或許有些疑問(wèn),本文就帶著這些疑問(wèn)為大家詳細(xì)介紹下,有疑問(wèn)的朋友可不要錯(cuò)過(guò)了哈2013-08-08JavaScript程序中實(shí)現(xiàn)繼承特性的方式總結(jié)
JavaScript是一門(mén)強(qiáng)行聲稱(chēng)面向?qū)ο蟮恼Z(yǔ)言,而繼承是面向?qū)ο蟮囊淮笾饕匦?這里我們根據(jù)阮一峰老師的文章來(lái)看一下JavaScript程序中實(shí)現(xiàn)繼承特性的方式總結(jié)2016-06-06js數(shù)組直接賦值的問(wèn)題(js數(shù)組的淺拷貝與深拷貝方法)
JS數(shù)組在直接賦值時(shí)屬于數(shù)組的淺拷貝,新數(shù)組保存的是原數(shù)據(jù)的內(nèi)存地址,修改新數(shù)組或原數(shù)組其中一個(gè)數(shù)組,另一個(gè)數(shù)組也會(huì)相應(yīng)的變化,數(shù)組的直接賦值屬于數(shù)組的淺拷貝,JS存儲(chǔ)對(duì)象都是存內(nèi)存地址2022-10-10JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記5 js語(yǔ)句
下面采用類(lèi)似的形式整理一下語(yǔ)句的相關(guān)知識(shí),重點(diǎn)突出一些ECMAScript中比較特別和個(gè)人認(rèn)為比較有意思的地方,同樣,沒(méi)有強(qiáng)調(diào)的但比較基礎(chǔ)的語(yǔ)句并非不重要,而是我認(rèn)為你已經(jīng)熟悉2012-10-10