摘要:明確重要的一點(diǎn),這個(gè)連接存在于實(shí)例與構(gòu)造函數(shù)的原型對象之間,而不是存在于實(shí)例與構(gòu)造函數(shù)之間。相當(dāng)于重新創(chuàng)建了,指向構(gòu)造函數(shù)這一部分相當(dāng)于是重新在原型對象中創(chuàng)建了一個(gè)屬性,同時(shí)指向構(gòu)造函數(shù)。
之前對js原型和原型鏈的理解一直覺得很繞,繞來繞去的,在看了《JavaScript高級程序設(shè)計(jì)》和各種文章之后,終于對原型和原型鏈有了初步的了解,可是還是沒有很深入的了解,今次通過以前段時(shí)間遇到的一道題,分析一下,用自己的想法進(jìn)行解讀,加深自己對原型和原型鏈的理解。
一、題目下面程序運(yùn)行結(jié)果是什么?
function Animal() { this.name = "Animal"; } Animal.prototype.changeName = function (name) { this.name = name; } function Cat() { this.name = "Cat"; } var animal = new Animal(); Cat.prototype = animal; Cat.prototype.constructor = Cat; var cat = new Cat(); animal.changeName("Tiger"); console.log(cat.name)
A. Animal
B. Cat
C. Tiger
D. 都不是
答案是 B Cat
二、解讀 1. 原型對象無論什么時(shí)候,只要?jiǎng)?chuàng)建了一個(gè)新函數(shù),就會(huì)根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個(gè)prototype屬性,這個(gè)屬性指向函數(shù)的原型對象。在默認(rèn)情況下,所有的原型對象都會(huì)自動(dòng)獲得一個(gè)constructor(構(gòu)造函數(shù))屬性,這個(gè)屬性是一個(gè)指向prototype屬性所在函數(shù)的指針。
下面用圖來說明
function Animal() { this.name = "Animal"; } Animal.prototype.changeName = function (name) { this.name = name; }
首先創(chuàng)建了一個(gè)Animal函數(shù),Animal中含有一個(gè)prototype屬性,指向Animal Prototype,而Animal.prototype.constructor指向Animal。這個(gè)時(shí)候由于name屬性是在函數(shù)中定義的,所以不在Animal Prototype中,而changeName 函數(shù)是通過Animal.prototype.changeName定義的,所以我們可以通過這種方式,在實(shí)例化多個(gè)對象時(shí),共享原型所保存的方法。
同理,當(dāng)創(chuàng)建了Cat函數(shù)時(shí),也是一樣。
function Cat() { this.name = "Cat"; }2. 創(chuàng)建實(shí)例
當(dāng)調(diào)用構(gòu)造函數(shù)創(chuàng)建一個(gè)新實(shí)例后,該實(shí)例的內(nèi)部將包含一個(gè)指針(內(nèi)部屬性),指向構(gòu)造函數(shù)的原型對象。在ECMA-262第5版中管這個(gè)指針叫[[Prototype]]。雖然在腳本中沒有標(biāo)準(zhǔn)的方式訪問[[Prototype]],但Firefox、Safari和Chrome在每個(gè)對象上都支持一個(gè)屬性__proto__。明確重要的一點(diǎn),這個(gè)連接存在于實(shí)例與構(gòu)造函數(shù)的原型對象之間,而不是存在于實(shí)例與構(gòu)造函數(shù)之間。
// 將Cat的原型對象指向animal實(shí)例,獲得animal中的屬性,原有的屬性丟失 Cat.prototype = animal;
這一部分相當(dāng)于是把Cat的原型對象的指針指向了animal實(shí)例,所以原來Cat原型對象中的constructor屬性丟失,替換成了animal實(shí)例中的屬性,包括name屬性以及__proto__內(nèi)部屬性,同時(shí)__proto__屬性也指向Animal.prototype,因此Cat也可以通過原型鏈查找調(diào)用到Animal中的屬性和方法。
// 相當(dāng)于重新創(chuàng)建了constructor,指向Cat構(gòu)造函數(shù) Cat.prototype.constructor = Cat;
這一部分相當(dāng)于是重新在原型對象中創(chuàng)建了一個(gè)constructor屬性,同時(shí)指向Cat構(gòu)造函數(shù)。
var cat = new Cat(); // 實(shí)例化一個(gè)Cat對象,跟實(shí)例化Animal相似3. 調(diào)用方法
animal.changeName("Tiger");
當(dāng)var animal = new Animal();實(shí)例化了一個(gè)Animal對象后,animal都包含一個(gè)內(nèi)部屬性,該屬性指向了Animal.prototype;換句話說,animal與構(gòu)造函數(shù)Animal沒有直接的關(guān)系??墒牵梢钥吹诫m然在實(shí)例中不含changeName,但我們卻可以調(diào)用animal.changeName(name),這是通過查找對象屬性的過程來實(shí)現(xiàn)的,即:
首先查找實(shí)例中實(shí)例中animal是否有changeName方法,如果沒有則繼續(xù)尋找,去到Animal.prototype尋找是否有changeName方法,如果有則調(diào)用,沒有則繼續(xù)尋找,到Object.prototype中尋找,最后沒找到則會(huì)返回一個(gè)null。
很明顯,在這里實(shí)例animal中沒有changeName方法,所以需要到Animal.prototype尋找changeName方法,并調(diào)用成功修改了實(shí)例animal中的name屬性,為Tiger。
這個(gè)時(shí)候由于Cat.prototype是指向?qū)嵗?b>animal的,因此Cat.prototype中的name屬性也變?yōu)?b>Tiger。
console.log(cat.name) // Cat
最后,獲取cat.name,與查找方法同樣,也是先去實(shí)例中cat查找是否含有name屬性,在這里很明顯是存在的,因此直接結(jié)束尋找,此時(shí)cat.name = "Cat"。
三、總結(jié)通過這道題,加深了我對原型和原型鏈的理解,其實(shí)這道題也可以擴(kuò)展到關(guān)于繼承的知識(shí)點(diǎn),在JavaScript中實(shí)現(xiàn)繼承主要是依靠原型鏈來實(shí)現(xiàn)。之后等我再搞的更清楚一點(diǎn)再繼續(xù)寫吧。
此文章是本人自己對于原型和原型鏈的一點(diǎn)小小的理解,中間可能存在偏差或者錯(cuò)誤的,請多多指點(diǎn)!??!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/98489.html
摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對象這種行為就像把原函數(shù)當(dāng)成構(gòu)造器。同時(shí),將第一個(gè)參數(shù)以外的其他參數(shù),作為提供給原函數(shù)的預(yù)設(shè)參數(shù),這也是基本的顆?;A(chǔ)。 今天想談?wù)勔坏狼岸嗣嬖囶},我做面試官的時(shí)候經(jīng)常喜歡用它來考察面試者的基礎(chǔ)是否扎實(shí),以及邏輯、思維能力和臨場表現(xiàn),題目是:模擬實(shí)現(xiàn)ES5中原生bind函數(shù)。也許這道題目已經(jīng)不再新鮮,部分讀者也會(huì)有思路來解答。社區(qū)上關(guān)于原生bind的研...
摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對象這種行為就像把原函數(shù)當(dāng)成構(gòu)造器。同時(shí),將第一個(gè)參數(shù)以外的其他參數(shù),作為提供給原函數(shù)的預(yù)設(shè)參數(shù),這也是基本的顆粒化基礎(chǔ)。 今天想談?wù)勔坏狼岸嗣嬖囶},我做面試官的時(shí)候經(jīng)常喜歡用它來考察面試者的基礎(chǔ)是否扎實(shí),以及邏輯、思維能力和臨場表現(xiàn),題目是:模擬實(shí)現(xiàn)ES5中原生bind函數(shù)。也許這道題目已經(jīng)不再新鮮,部分讀者也會(huì)有思路來解答。社區(qū)上關(guān)于原生bind的研...
摘要:返回的綁定函數(shù)也能使用操作符創(chuàng)建對象這種行為就像把原函數(shù)當(dāng)成構(gòu)造器。同時(shí),將第一個(gè)參數(shù)以外的其他參數(shù),作為提供給原函數(shù)的預(yù)設(shè)參數(shù),這也是基本的顆粒化基礎(chǔ)。 今天想談?wù)勔坏狼岸嗣嬖囶},我做面試官的時(shí)候經(jīng)常喜歡用它來考察面試者的基礎(chǔ)是否扎實(shí),以及邏輯、思維能力和臨場表現(xiàn),題目是:模擬實(shí)現(xiàn)ES5中原生bind函數(shù)。也許這道題目已經(jīng)不再新鮮,部分讀者也會(huì)有思路來解答。社區(qū)上關(guān)于原生bind的研...
摘要:那么什么是基礎(chǔ)對象組件呢,舉兩個(gè)例子我們再來看看屬性訪問器,就是括號操作符及點(diǎn)號操作符都做了什么屬性訪問器也就是說括號跟點(diǎn)號對解釋器而言是一樣的。 ES規(guī)范解讀之賦值操作符&屬性訪問器 原文:https://github.com/kuitos/kuitos.github.io/issues/24事情起源于某天某妹子同事在看angular文檔中關(guān)于Scope的說明Understandin...
摘要:但這兩個(gè)對象的原型指向了同一個(gè)實(shí)例對象,這個(gè)實(shí)例對象同樣是存在棧內(nèi)存中的然后指向了一個(gè)對象。實(shí)際是在的實(shí)例對象增加一個(gè)屬性,并將屬性賦值為,但它并沒有修改原型鏈上的屬性。側(cè)重理解的指向問題 直接先貼題目吧 function A() { this.name = a this.color = [green, yellow] } function B() { ...
閱讀 1565·2023-04-26 01:36
閱讀 2730·2021-10-08 10:05
閱讀 2784·2021-08-05 09:57
閱讀 1544·2019-08-30 15:52
閱讀 1200·2019-08-30 14:12
閱讀 1320·2019-08-30 11:17
閱讀 3110·2019-08-29 13:07
閱讀 2429·2019-08-29 12:35