摘要:是構(gòu)造函數(shù)的屬性,而不是實(shí)例對(duì)象的屬性,指向原型對(duì)象。這個(gè)連接存在于實(shí)例與構(gòu)造函數(shù)的原型對(duì)象而不是構(gòu)造函數(shù)之間,也就是說(shuō)實(shí)例對(duì)象與構(gòu)造函數(shù)沒(méi)有直接關(guān)系。
prototype、constructor、__proto__
??prototype是站在構(gòu)造函數(shù)的角度討論原型對(duì)象的,用來(lái)實(shí)現(xiàn)基于原型的繼承與屬性的共享。__proto__是站在實(shí)例對(duì)象的角度討論原型對(duì)象,構(gòu)成原型鏈,同樣用于實(shí)現(xiàn)基于原型的繼承。
function Person(){} var p = new Person();
Person.prototype
Person.constructor
p.prototype
p.constructor
p.__proto__
通過(guò)new構(gòu)造函數(shù)實(shí)例化得到對(duì)象。
prototype是構(gòu)造函數(shù)的屬性,而不是實(shí)例對(duì)象的屬性,指向Person.prototype原型對(duì)象。
實(shí)例對(duì)象含有一個(gè)Constructor屬性指向該對(duì)象的構(gòu)造器。
p對(duì)象有個(gè)__proto__內(nèi)部屬性指向Person.prototype。
p.__proto__、p.constructor.prototype、Person.prototype指向Person的原型對(duì)象
??每個(gè)構(gòu)造函數(shù)都有一個(gè)phototype屬性(通過(guò)Function.prototype.bind方法構(gòu)造出來(lái)的函數(shù)以及Object.create(null)例外,沒(méi)有prototype屬性),這個(gè)屬性是一個(gè)指針,指向一個(gè)包含特定類(lèi)型的所有實(shí)例共享屬性和方法的對(duì)象。通過(guò)prototype對(duì)象可以返回對(duì)象的原型對(duì)象的引用。
??每個(gè)實(shí)例對(duì)象都有一個(gè)constructor屬性指向prototype屬性所在函數(shù)的指針。通過(guò)這個(gè)constructor(構(gòu)造函數(shù)),還可以繼續(xù)為原型對(duì)象添加其他屬性和方法。
??每個(gè)實(shí)例對(duì)象都有一個(gè)內(nèi)部屬性[[prototype]],在ES5之前沒(méi)有標(biāo)準(zhǔn)的方法訪問(wèn)這個(gè)內(nèi)置屬性,但是大多數(shù)瀏覽器都支持通過(guò)__proto__指針來(lái)訪問(wèn)。__proto__指向?qū)嵗搶?duì)象的構(gòu)造器的原型對(duì)象(Object.prototype 這個(gè)對(duì)象是個(gè)例外,它的__proto__值為null)。這個(gè)連接存在于實(shí)例與構(gòu)造函數(shù)的原型對(duì)象(而不是構(gòu)造函數(shù))之間,也就是說(shuō)實(shí)例對(duì)象與構(gòu)造函數(shù)沒(méi)有直接關(guān)系。并且,實(shí)例并不包含屬性與方法,實(shí)例之所以能夠調(diào)用原型上的方法,是依賴(lài)于查找對(duì)象屬性的過(guò)程來(lái)實(shí)現(xiàn)的。雖然無(wú)法訪問(wèn)到__proto__,可以通過(guò)isPrototypeOf()方法來(lái)確定對(duì)象之間是否存在這種關(guān)系,如果__proto__指向調(diào)用該方法的對(duì)象的prototype,返回true。
console.log(Person.prototype.isPrototypeOf(p)); //true;
??每當(dāng)代碼讀取某個(gè)對(duì)象屬性時(shí),首先從對(duì)象實(shí)例開(kāi)始,如果找到給定名字屬性,返回該值;如果沒(méi)有找到,繼續(xù)搜索指針指向的原型對(duì)象。雖然能通過(guò)實(shí)例訪問(wèn)原型中的值,但不能通過(guò)對(duì)象實(shí)例重寫(xiě)原型中的值。
??當(dāng)為對(duì)象實(shí)例添加一個(gè)屬性時(shí),這個(gè)屬性就會(huì)屏蔽原型對(duì)象中保存的同名屬性;換句話(huà)說(shuō),添加這個(gè)屬性只會(huì)阻止我們?cè)L問(wèn)原型中的那個(gè)屬性,但不會(huì)修改那個(gè)屬性。即使將這個(gè)屬性設(shè)置為 null,也只會(huì)在實(shí)例中設(shè)置這個(gè)屬性,而不會(huì)恢復(fù)其指向原型的連接。不過(guò),使用 delete 操作符則可以完全刪除實(shí)例屬性,從而讓我們能夠重新訪問(wèn)原型中的屬性。
function Person(){} Person.prototype.name = "staven"; Person.prototype.say = function(){ console.log("My name is "+this.name); } var p = new Person(); p.name = "赫連小妖" p.say(); //My name is 赫連小妖 delete p.name; p.say(); //My name is staven
??使用 hasOwnProperty()方法只在給定屬性存在于對(duì)象實(shí)例中時(shí),才會(huì)返回 true;可以檢測(cè)一個(gè)屬性是存在于實(shí)例中,還是存在于原型中。
??for(x in xxx)既可以檢測(cè)實(shí)例屬性,也可以檢測(cè)自定義屬性。
??hasOwnProperty()為true,屬性存在在對(duì)象實(shí)例中;hasOwnProperty()為false,(x in xxx)為true,屬性存在在對(duì)象的構(gòu)造器原型中。
function Person(){} Person.prototype.name = "staven"; var p = new Person(); console.log(p.hasOwnProperty("name")); //false console.log(("name" in p)); //true p.name = "赫連小妖"; console.log(p.hasOwnProperty("name")); //true console.log(("name" in p)); //true
??ECMAScript 5 的 Object.keys()方法接收一個(gè)對(duì)象作為參數(shù),返回一個(gè)包含所有可枚舉屬性的字符串?dāng)?shù)組。
function Person(){} Person.prototype.name = "staven"; Person.prototype.say = function(){}; console.log(Object.keys(Person.prototype)); //["name", "say"] var p = new Person(); p.sex = "man"; p.character = "handsome"; console.log(Object.keys(p)); //["sex", "character"]
??無(wú)論它是否可枚舉,都可以使用 Object.getOwnPropertyNames()方法。
function Person(){} Person.prototype.name = "staven"; Person.prototype.say = function(){}; console.log(Object.getOwnPropertyNames(Person.prototype)); //["constructor", "name", "say"] var p = new Person(); p.sex = "man"; p.character = "handsome"; console.log(Object.getOwnPropertyNames(p)); //["sex", "character"]使用字面量賦值原型對(duì)象
Person.prototype = { name : "staven", say : function(){ console.log("My name is "+this.name); } };
??此時(shí)constructor屬性不再指向Person。盡管 instanceof操作符還能返回正確的結(jié)果,但通過(guò) constructor 已經(jīng)無(wú)法確定對(duì)象的類(lèi)型了。
function Person(){} Person.prototype = { name : "staven", say : function(){ console.log("My name is "+this.name); } }; var p = new Person(); console.log(p instanceof Object); //true console.log(p instanceof Person); //true console.log(p.constructor == Person); //false console.log(p.constructor == Object); //true
??不過(guò)可以重新設(shè)置constructor屬性,確保通過(guò)該屬性的原有性。
function Person(){} Person.prototype = { constructor : Person, name : "staven", say : function(){ console.log("My name is "+this.name); } };原型的動(dòng)態(tài)性
??隨時(shí)可以為原型添加屬性和方法,并且能夠立即在所有對(duì)象實(shí)例中反映出來(lái),但是如果重寫(xiě)了整個(gè)原型對(duì)象,情況就不同了。調(diào)用構(gòu)造函數(shù)時(shí)會(huì)為實(shí)例添加一個(gè)[[Prototype]]指針,把原型修改為另一個(gè)對(duì)象,就相當(dāng)于切斷了構(gòu)造函數(shù)與最初原型之間的聯(lián)系。
function Person(){} var p = new Person(); Person.prototype = { constructor : Person, name : "staven", say : function(){ console.log("My name is "+this.name); } }; p.say(); //Uncaught TypeError: p.say is not a function原型對(duì)象的缺點(diǎn)
??省略了為構(gòu)造函數(shù)傳遞初始化參數(shù),結(jié)果所有實(shí)例在默認(rèn)情況下都將取得相同的屬性值。
??由于原型的屬性共享,若在實(shí)例上添加一個(gè)同名的包含引用類(lèi)型值得的屬性,其他實(shí)例該屬性也會(huì)被改變。
function Person(){} Person.prototype = { books:["html5","css3","js"] } var p1 = new Person(); var p2 = new Person(); p1.books.pop(); console.log(p1.books); //["html5", "css3"] console.log(p2.books); //["html5", "css3"]
???深究JavaScript系列???
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92166.html
摘要:構(gòu)造函數(shù)和實(shí)例都通過(guò)屬性指向了原形。代碼示例是構(gòu)造函數(shù)的實(shí)例的屬性與的屬性保存的值相等,即他們指向同一個(gè)對(duì)象原形。 講清楚之javascript原型 標(biāo)簽: javascript javascript 中原形是一個(gè)比較難于理解的概念。javascript 權(quán)威指南在原形這一章也花了大量的篇幅進(jìn)行介紹,也許你已經(jīng)讀過(guò)javascript 權(quán)威指南,或者已經(jīng)是讀第N篇了,然而這篇文章的目...
摘要:原型鏈?zhǔn)紫?,的?duì)象普通對(duì)象和函數(shù)對(duì)象都會(huì)有屬性,指向創(chuàng)建它的構(gòu)造函數(shù)的原型對(duì)象,比如上面的例子這就形成了原型鏈,會(huì)一直查找原型對(duì)象的屬性,直到為。,保證原型鏈能夠正常結(jié)束。 前言 一般談到j(luò)s中的繼承的時(shí)候,一定會(huì)遇到原型,原型鏈的問(wèn)題,原型里面又有prototype,__proto__,constructor屬性,講到這兒,很多同學(xué)是不是都一頭霧水,傻傻分不清楚,因?yàn)楣ぷ髦杏玫降牡胤?..
摘要:然而事實(shí)上并不是。函數(shù)本身也是一個(gè)對(duì)象,但是給這個(gè)對(duì)象添加屬性并不能影響。一圖勝千言作者給出的解決方案,沒(méi)有麻煩的,沒(méi)有虛偽的,沒(méi)有混淆視線(xiàn)的,原型鏈連接不再赤裸裸。所以是這樣的一個(gè)函數(shù)以為構(gòu)造函數(shù),為原型。 注意:本文章是個(gè)人《You Don’t Know JS》的讀書(shū)筆記。在看backbone源碼的時(shí)候看到這么一小段,看上去很小,其實(shí)忽略了也沒(méi)有太大理解的問(wèn)題。但是不知道為什么,我...
摘要:深入理解原型與繼承看過(guò)不少書(shū)籍,不少文章,對(duì)于原型與繼承的說(shuō)明基本上讓人不明覺(jué)厲,特別是對(duì)于習(xí)慣了面向?qū)ο缶幊痰娜藖?lái)說(shuō)更難理解,這里我就給大家說(shuō)說(shuō)我的理解。 深入理解:JavaScript原型與繼承 看過(guò)不少書(shū)籍,不少文章,對(duì)于原型與繼承的說(shuō)明基本上讓人不明覺(jué)厲,特別是對(duì)于習(xí)慣了面向?qū)ο缶幊痰娜藖?lái)說(shuō)更難理解,這里我就給大家說(shuō)說(shuō)我的理解。 首先JavaScript是一門(mén)基于原型編程的語(yǔ)言...
閱讀 1325·2023-04-26 03:05
閱讀 782·2021-10-19 11:43
閱讀 3232·2021-09-26 09:55
閱讀 837·2019-08-30 15:56
閱讀 998·2019-08-30 15:44
閱讀 1250·2019-08-30 15:44
閱讀 2731·2019-08-30 14:23
閱讀 3247·2019-08-30 13:13