摘要:這篇文章的的目的試圖通過最簡單的表述讓大家理解和先把最重要的幾點(diǎn)列出來大家可以帶著這幾個(gè)核心要點(diǎn)閱讀下面的文章是用來在原型鏈上查找你需要的方法的實(shí)際對象所有的對象都有這個(gè)屬性這個(gè)屬性被引擎用作繼承使用根據(jù)的規(guī)范這個(gè)屬性應(yīng)該是一個(gè)內(nèi)在的屬性但
這篇文章的的目的試圖通過最簡單的表述,讓大家理解prototype和__proto__
先把最重要的幾點(diǎn)列出來,大家可以帶著這幾個(gè)核心要點(diǎn)閱讀下面的文章.
__proto__是用來在原型鏈上查找你需要的方法的實(shí)際對象,所有的對象都有這個(gè)屬性.這個(gè)屬性被JavaScript引擎用作繼承使用.
根據(jù)ECMA的規(guī)范,這個(gè)屬性應(yīng)該是一個(gè)內(nèi)在的屬性,但是大多數(shù)的瀏覽器廠商都允許我們?nèi)ピL問和修改它.
prototype是函數(shù)獨(dú)有的屬性.當(dāng)我們使用關(guān)鍵詞new并且將函數(shù)作為構(gòu)造函數(shù)來構(gòu)造對象的時(shí)候,
它被用來構(gòu)建對象的__proto__屬性.
__proto__屬性和prototype屬性都是一個(gè)對象代碼演示.
(new A()).__proto__ === A.prototype的結(jié)果為true,(new A()).prototype === undefined的結(jié)果也為true,其中A表示一個(gè)函數(shù)(也就是構(gòu)造函數(shù)).
接下來我們來使用一些代碼來解釋上面所說的那些要點(diǎn):代碼演示
// 這是一個(gè)普通函數(shù),我們把它用來當(dāng)做構(gòu)造函數(shù),也當(dāng)做一個(gè)[父類] function Car(name) { this.name = name; } Car.prototype.introduce = function() { console.log("[From Car.prototype.introduce] " + "Hello, my name is: " + this.name); }; var car = new Car("porsche"); console.log(car.name); // porsche car.introduce(); // [From Car.prototype.introduce] Hello, my name is: porsche // 我們開始構(gòu)建另外一個(gè)函數(shù),我們把這個(gè)函數(shù)當(dāng)做一個(gè)[子類],暫時(shí)這么說. function MiniCar(name, color) { this.name = name; this.color = color; this.getColor = function() { console.log("My color is: " + this.color); } } MiniCar.prototype = new Car(); var miniCar = new MiniCar("benz", "black"); console.log(" "); console.log("name: " + miniCar.name + ";color: " + miniCar.color); // name: benz;color: black miniCar.introduce(); // [From Car.prototype.introduce] Hello, my name is: benz miniCar.getColor(); // My color is: black // 如果使用A表示一個(gè)構(gòu)造函數(shù),那么 (new A()).__proto__ === A.prototype console.log((new MiniCar()).__proto__ === MiniCar.prototype); // true // 如果使用a表示A的一個(gè)示例的話,那么 a.__proto__ === A.prototype console.log(miniCar.__proto__ === MiniCar.prototype); // true // 一個(gè)對象是沒有prototype屬性的 console.log(miniCar.prototype === undefined); // true
如果你練習(xí)了上面的代碼,對這兩個(gè)屬性的理解應(yīng)該會(huì)有一定的幫助,也許你已經(jīng)理解了;如果沒有太懂的話,那也沒關(guān)系;我們下面來好好的說一說上面的代碼(開始長篇大論了).
首先,在JavaScript中是沒有類這個(gè)概念的,如果你學(xué)過Java或者C++的話,應(yīng)該知道,要是想創(chuàng)建一個(gè)對象,必須先有一個(gè)類;但是JavaScript中沒有類,那怎么辦?模仿嘍,所以JavaScript創(chuàng)造了__proto__這個(gè)屬性用來連接子類和父類.創(chuàng)造了prototype屬性去用來在構(gòu)建子類時(shí)候構(gòu)建__proto__這個(gè)屬性.
這里先暫停上面的線程,我們來說說prototype這個(gè)屬性,這個(gè)屬性是只屬于Function函數(shù)的,那么這個(gè)屬性的作用是什么呢?這個(gè)屬性的作用是為了讓使用Function作為構(gòu)造函數(shù)new出來的對象實(shí)例都能夠共享一些函數(shù).
function Car(name) { this.name = name; } Car.prototype.introduce = function() { console.log("[From Car.prototype.introduce] " + "Hello, my name is: " + this.name); };
上面的代碼中,只要是使用Car這個(gè)構(gòu)造函數(shù)new出來的對象都具有方法introduce.
繼續(xù)上面的線程,我們按照代碼的執(zhí)行順序來說明這件事情:
首先我們定義了兩個(gè)函數(shù)Car和MiniCar,如下圖所示:
然后我們給Car的原型上添加了一個(gè)方法introduce,如下圖所示:
接下來var car = new Car("porsche")這一行代碼可不像它看起來那樣,它內(nèi)部的實(shí)現(xiàn)還是有許多值得玩味的;首先,函數(shù)Car創(chuàng)建了一個(gè)新的對象(a),這個(gè)對象有一個(gè)隱藏的屬性__proto__,這個(gè)屬性和Car的原型都指向同一個(gè)對象.然后Car函數(shù)內(nèi)部的this指向哪個(gè)新創(chuàng)建的對象(a).如下圖所示:
然后我們給這個(gè)對象添加了一個(gè)屬性name,并且為其賦值.還要注意的一點(diǎn)是,我們這個(gè)Car函數(shù)是有返回值的,雖然沒有使用return關(guān)鍵字把這個(gè)值顯式的返回,這個(gè)返回值是一個(gè)引用,然后變量car就可以用來操作那個(gè)對象了(a).
然后上面的語句運(yùn)行完之后,場面上是下圖這個(gè)樣子:
接下來我們輸出了這個(gè)對象的名字,然后調(diào)用了這個(gè)對象(的構(gòu)造函數(shù)的原型上的)的introduce方法.輸出的結(jié)果如下圖:
然后我們有定義了一個(gè)函數(shù)MiniCar,我們把它當(dāng)做Car(父類)的一個(gè)子類;我使用代碼MiniCar.prototype = new Car()來實(shí)現(xiàn)這個(gè)功能,這段代碼更值得好好分析一下.
首先如上圖所示,MiniCar這個(gè)函數(shù)的prototype是函數(shù)Car使用new關(guān)鍵字創(chuàng)建的一個(gè)對象(b),所以MiniCar的實(shí)例具有這個(gè)對象(b)能夠使用的任何屬性和方法.
讓我們更進(jìn)一步吧,這一步我們開始運(yùn)行var miniCar = new MiniCar("benz", "black")這段代碼,首先我們先要運(yùn)行函數(shù)MiniCar函數(shù),所以通過new操作,我們新創(chuàng)建了一個(gè)對象(c),我們首先給這個(gè)對象添加了了兩個(gè)屬性,分別是name和color,然后分別賦值benz和black,其實(shí)我們可以只添加一個(gè)屬性,因?yàn)?b>name屬性在Car上是已經(jīng)存在的.我們還給它添加了一個(gè)getColor方法,它的__proto__屬性指向MiniCar.prototype, 而MiniCar.prototype是一個(gè)對象,這個(gè)對象也有一個(gè)__proto__屬性,這個(gè)屬性指向Car.prototype,如此一來這個(gè)偽繼承就實(shí)現(xiàn)了.然后我們將這個(gè)對象(c)的索引賦值給miniCar,所以通過miniCar可以操作對象(c).
然后接下來的一切應(yīng)該都順理成章了.
原文的地址github
參考的文章或者問答:
How does proto differ from constructor.prototype?
proto VS. prototype in JavaScript
Inheritance and the prototype chain
JavaScript difference between proto and prototype
Understanding "Prototypes" in JavaScript
JavaScript Prototype in Plain Language
Object.prototype.__proto__
Function.prototype
js中__proto__和prototype的區(qū)別和關(guān)系?
prototype與__proto__的聯(lián)系與區(qū)別
簡單粗暴地理解js原型鏈--js面向?qū)ο缶幊?/p>
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/79645.html
摘要:深入理解原型與繼承看過不少書籍,不少文章,對于原型與繼承的說明基本上讓人不明覺厲,特別是對于習(xí)慣了面向?qū)ο缶幊痰娜藖碚f更難理解,這里我就給大家說說我的理解。 深入理解:JavaScript原型與繼承 看過不少書籍,不少文章,對于原型與繼承的說明基本上讓人不明覺厲,特別是對于習(xí)慣了面向?qū)ο缶幊痰娜藖碚f更難理解,這里我就給大家說說我的理解。 首先JavaScript是一門基于原型編程的語言...
摘要:面向?qū)ο髮?shí)現(xiàn)代碼動(dòng)物發(fā)聲汪汪喵喵調(diào)用代碼動(dòng)物發(fā)聲喵喵動(dòng)物發(fā)聲汪汪當(dāng)要增加一種動(dòng)物時(shí),只需增加一個(gè)繼承,不會(huì)影響其他已有的動(dòng)物邏輯。所以的繼承和的原型繼承,可謂殊途同歸。 傳統(tǒng)面向?qū)ο蟮睦^承和多態(tài) 我們知道C++/Java/C#等面向?qū)ο笳Z言,都原生地支持類的繼承。繼承的核心作用大抵是創(chuàng)建一個(gè)派生類,并使其復(fù)用基本類(即父類)的字段和/或方法。并且派生類可以重寫基本類的方法。這樣基本類和...
摘要:而作為構(gòu)造函數(shù),需要有個(gè)屬性用來作為以該構(gòu)造函數(shù)創(chuàng)造的實(shí)例的繼承。 歡迎來我的博客閱讀:「JavaScript 原型中的哲學(xué)思想」 記得當(dāng)年初試前端的時(shí)候,學(xué)習(xí)JavaScript過程中,原型問題一直讓我疑惑許久,那時(shí)候捧著那本著名的紅皮書,看到有關(guān)原型的講解時(shí),總是心存疑慮。 當(dāng)在JavaScript世界中走過不少旅程之后,再次萌發(fā)起研究這部分知識(shí)的欲望,翻閱了不少書籍和資料,才搞懂...
摘要:構(gòu)造函數(shù)和實(shí)例都通過屬性指向了原形。代碼示例是構(gòu)造函數(shù)的實(shí)例的屬性與的屬性保存的值相等,即他們指向同一個(gè)對象原形。 講清楚之javascript原型 標(biāo)簽: javascript javascript 中原形是一個(gè)比較難于理解的概念。javascript 權(quán)威指南在原形這一章也花了大量的篇幅進(jìn)行介紹,也許你已經(jīng)讀過javascript 權(quán)威指南,或者已經(jīng)是讀第N篇了,然而這篇文章的目...
閱讀 2531·2021-09-28 09:36
閱讀 3672·2021-09-22 15:41
閱讀 4540·2021-09-04 16:45
閱讀 2181·2019-08-30 15:55
閱讀 2905·2019-08-30 13:49
閱讀 897·2019-08-29 16:34
閱讀 2444·2019-08-29 12:57
閱讀 1737·2019-08-26 18:42