摘要:是構造函數的屬性,而不是實例對象的屬性,指向原型對象。這個連接存在于實例與構造函數的原型對象而不是構造函數之間,也就是說實例對象與構造函數沒有直接關系。
prototype、constructor、__proto__
??prototype是站在構造函數的角度討論原型對象的,用來實現基于原型的繼承與屬性的共享。__proto__是站在實例對象的角度討論原型對象,構成原型鏈,同樣用于實現基于原型的繼承。
function Person(){} var p = new Person();
Person.prototype
Person.constructor
p.prototype
p.constructor
p.__proto__
通過new構造函數實例化得到對象。
prototype是構造函數的屬性,而不是實例對象的屬性,指向Person.prototype原型對象。
實例對象含有一個Constructor屬性指向該對象的構造器。
p對象有個__proto__內部屬性指向Person.prototype。
p.__proto__、p.constructor.prototype、Person.prototype指向Person的原型對象
??每個構造函數都有一個phototype屬性(通過Function.prototype.bind方法構造出來的函數以及Object.create(null)例外,沒有prototype屬性),這個屬性是一個指針,指向一個包含特定類型的所有實例共享屬性和方法的對象。通過prototype對象可以返回對象的原型對象的引用。
??每個實例對象都有一個constructor屬性指向prototype屬性所在函數的指針。通過這個constructor(構造函數),還可以繼續為原型對象添加其他屬性和方法。
??每個實例對象都有一個內部屬性[[prototype]],在ES5之前沒有標準的方法訪問這個內置屬性,但是大多數瀏覽器都支持通過__proto__指針來訪問。__proto__指向實例該對象的構造器的原型對象(Object.prototype 這個對象是個例外,它的__proto__值為null)。這個連接存在于實例與構造函數的原型對象(而不是構造函數)之間,也就是說實例對象與構造函數沒有直接關系。并且,實例并不包含屬性與方法,實例之所以能夠調用原型上的方法,是依賴于查找對象屬性的過程來實現的。雖然無法訪問到__proto__,可以通過isPrototypeOf()方法來確定對象之間是否存在這種關系,如果__proto__指向調用該方法的對象的prototype,返回true。
console.log(Person.prototype.isPrototypeOf(p)); //true;
??每當代碼讀取某個對象屬性時,首先從對象實例開始,如果找到給定名字屬性,返回該值;如果沒有找到,繼續搜索指針指向的原型對象。雖然能通過實例訪問原型中的值,但不能通過對象實例重寫原型中的值。
??當為對象實例添加一個屬性時,這個屬性就會屏蔽原型對象中保存的同名屬性;換句話說,添加這個屬性只會阻止我們訪問原型中的那個屬性,但不會修改那個屬性。即使將這個屬性設置為 null,也只會在實例中設置這個屬性,而不會恢復其指向原型的連接。不過,使用 delete 操作符則可以完全刪除實例屬性,從而讓我們能夠重新訪問原型中的屬性。
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()方法只在給定屬性存在于對象實例中時,才會返回 true;可以檢測一個屬性是存在于實例中,還是存在于原型中。
??for(x in xxx)既可以檢測實例屬性,也可以檢測自定義屬性。
??hasOwnProperty()為true,屬性存在在對象實例中;hasOwnProperty()為false,(x in xxx)為true,屬性存在在對象的構造器原型中。
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()方法接收一個對象作為參數,返回一個包含所有可枚舉屬性的字符串數組。
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"]
??無論它是否可枚舉,都可以使用 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"]使用字面量賦值原型對象
Person.prototype = { name : "staven", say : function(){ console.log("My name is "+this.name); } };
??此時constructor屬性不再指向Person。盡管 instanceof操作符還能返回正確的結果,但通過 constructor 已經無法確定對象的類型了。
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
??不過可以重新設置constructor屬性,確保通過該屬性的原有性。
function Person(){} Person.prototype = { constructor : Person, name : "staven", say : function(){ console.log("My name is "+this.name); } };原型的動態性
??隨時可以為原型添加屬性和方法,并且能夠立即在所有對象實例中反映出來,但是如果重寫了整個原型對象,情況就不同了。調用構造函數時會為實例添加一個[[Prototype]]指針,把原型修改為另一個對象,就相當于切斷了構造函數與最初原型之間的聯系。
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原型對象的缺點
??省略了為構造函數傳遞初始化參數,結果所有實例在默認情況下都將取得相同的屬性值。
??由于原型的屬性共享,若在實例上添加一個同名的包含引用類型值得的屬性,其他實例該屬性也會被改變。
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系列???
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/92166.html
摘要:構造函數和實例都通過屬性指向了原形。代碼示例是構造函數的實例的屬性與的屬性保存的值相等,即他們指向同一個對象原形。 講清楚之javascript原型 標簽: javascript javascript 中原形是一個比較難于理解的概念。javascript 權威指南在原形這一章也花了大量的篇幅進行介紹,也許你已經讀過javascript 權威指南,或者已經是讀第N篇了,然而這篇文章的目...
摘要:原型鏈首先,的對象普通對象和函數對象都會有屬性,指向創建它的構造函數的原型對象,比如上面的例子這就形成了原型鏈,會一直查找原型對象的屬性,直到為。,保證原型鏈能夠正常結束。 前言 一般談到js中的繼承的時候,一定會遇到原型,原型鏈的問題,原型里面又有prototype,__proto__,constructor屬性,講到這兒,很多同學是不是都一頭霧水,傻傻分不清楚,因為工作中用到的地方...
摘要:然而事實上并不是。函數本身也是一個對象,但是給這個對象添加屬性并不能影響。一圖勝千言作者給出的解決方案,沒有麻煩的,沒有虛偽的,沒有混淆視線的,原型鏈連接不再赤裸裸。所以是這樣的一個函數以為構造函數,為原型。 注意:本文章是個人《You Don’t Know JS》的讀書筆記。在看backbone源碼的時候看到這么一小段,看上去很小,其實忽略了也沒有太大理解的問題。但是不知道為什么,我...
摘要:深入理解原型與繼承看過不少書籍,不少文章,對于原型與繼承的說明基本上讓人不明覺厲,特別是對于習慣了面向對象編程的人來說更難理解,這里我就給大家說說我的理解。 深入理解:JavaScript原型與繼承 看過不少書籍,不少文章,對于原型與繼承的說明基本上讓人不明覺厲,特別是對于習慣了面向對象編程的人來說更難理解,這里我就給大家說說我的理解。 首先JavaScript是一門基于原型編程的語言...
閱讀 1316·2023-04-26 03:05
閱讀 773·2021-10-19 11:43
閱讀 3218·2021-09-26 09:55
閱讀 829·2019-08-30 15:56
閱讀 986·2019-08-30 15:44
閱讀 1239·2019-08-30 15:44
閱讀 2721·2019-08-30 14:23
閱讀 3237·2019-08-30 13:13