摘要:在中,萬(wàn)物皆對(duì)象。在日常中,我們除了經(jīng)常聽(tīng)到原型這個(gè)詞之外,還經(jīng)常會(huì)聽(tīng)到原型鏈這個(gè)詞,那么這兩個(gè)詞到底有什么關(guān)系呢,下面我們就來(lái)探究一下。指向的對(duì)象往往被稱為函數(shù)的原型。很簡(jiǎn)單,委托實(shí)際上就是原型鏈。
在JavaScript中,萬(wàn)物皆對(duì)象。每個(gè)對(duì)象都有一個(gè)特殊的內(nèi)部屬性,[[Prototype]](原型)。它是對(duì)于其他對(duì)象的引用,也就是說(shuō)它關(guān)聯(lián)到別的對(duì)象(如果它不為空)。
在日常中,我們除了經(jīng)常聽(tīng)到原型這個(gè)詞之外,還經(jīng)常會(huì)聽(tīng)到原型鏈這個(gè)詞,那么這兩個(gè)詞到底有什么關(guān)系呢,下面我們就來(lái)探究一下。
那首先我們來(lái)看一下[[Prototype]]這個(gè)特殊的內(nèi)部屬性有什么用呢?我們先來(lái)講一個(gè)關(guān)于屬性訪問(wèn)的一些知識(shí)??聪旅娴拇a:
var myObject = { a:1; }; myObject.a; //1
在這里,我們可以清楚的看到Object.a是一個(gè)屬性訪問(wèn)(訪問(wèn)了Object的a屬性),那么深入一下,上面的代碼實(shí)際上在Object上執(zhí)行了一個(gè)[[Get]]操作。對(duì)一個(gè)對(duì)象執(zhí)行默認(rèn)的[[Get]]操作,會(huì)首先檢查對(duì)象,尋找請(qǐng)求的屬性,如果找到,就返回相應(yīng)的值。如果沒(méi)找到,這個(gè)時(shí)候?qū)ο蟮?b>[[Prototype]]屬性以及它的[[Prototype]]鏈就需要派上用場(chǎng)了。
先看代碼:
var newObject = { a:1; }; var myObject = Object.create(newObject); myObject.a; //1
首先我們可以看到在上面的代碼中,a這個(gè)屬性是不存在myObject這個(gè)對(duì)象里的,但是最后我們還是得到了a這個(gè)屬性的值。
var myObject = Object.create(newObject);這行代碼就是關(guān)鍵了。它創(chuàng)建了一個(gè)對(duì)象myObject關(guān)聯(lián)到newObject。也就是說(shuō)myObject的[[Prototype]]屬性關(guān)聯(lián)到了newObject這個(gè)對(duì)象。[[Get]]操作在對(duì)象本身沒(méi)找到需要的屬性后,便順著這個(gè)關(guān)聯(lián)去newObject這個(gè)對(duì)象里進(jìn)行查找。
所以在對(duì)屬性進(jìn)行查詢的時(shí)候,就會(huì)順著這個(gè)一層又一層的關(guān)聯(lián),也就是所謂的[[Prototype]]鏈,對(duì)需要的屬性進(jìn)行查找。在[[Prototype]]鏈找到了就返回屬性值或者在鏈條的末尾都沒(méi)找到就返回undefined。那么鏈條的末尾是什么呢?每個(gè)普通的[[Prototype]]鏈的最頂端,是內(nèi)建的Object.prototype,也就是null。
開(kāi)頭講到,[[Prototype]]這個(gè)屬性是把一個(gè)對(duì)象關(guān)聯(lián)到另一個(gè)對(duì)象。那么這個(gè)關(guān)聯(lián)有什么用呢?
常見(jiàn)的用法那就是所謂的原型繼承和委托了。
我們通過(guò)代碼來(lái)理解一下:
function Foo(a) { this.a = a; } Foo.prototype.myA = function() { return this.a; }; function Bar(a,b) { Foo.call(this,a); this.b = b; } Bar.prototype = Object.create(Foo.prototype); Bar.prototype.myB = function() { return this.b; }; var Baz = new Bar( "1", "obj 1" ); Baz.myA(); // "1" Baz.myB(); // "obj 1"
在上面的代碼中,最重要的部分就是Bar.prototype = Object.create(Foo.prototype);。這個(gè)代碼應(yīng)該會(huì)比較眼熟,因?yàn)樵谏厦娴睦又形覀円灿玫搅讼嗨频拇a,并且解釋說(shuō)是把一個(gè)對(duì)象關(guān)聯(lián)到另一個(gè)對(duì)象上。那么這里我們是把新創(chuàng)建的Bar對(duì)象的內(nèi)部的[[Prototype]]鏈接到了指定的對(duì)象Foo.prototype。
Bar和Foo在這里既是對(duì)象也是函數(shù)。函數(shù)有一個(gè)性質(zhì):所有的函數(shù)默認(rèn)都會(huì)得到一個(gè)可以指向任何對(duì)象的屬性prototype。
指向的對(duì)象往往被稱為“函數(shù)的原型”。每個(gè)由調(diào)用new Foo()而創(chuàng)建的對(duì)象將最終被[[Prototype]]鏈接到所謂的“函數(shù)的原型”。
看段代碼來(lái)深入了解一下:
function Foo(a){ this.a = a; } var bar = new Foo(2); bar.a; //2 Object.getPrototypeOf(bar) === Foo.prototype; //true
那么為什么調(diào)用new Foo()創(chuàng)建的對(duì)象可以鏈接到函數(shù)原型呢?這就跟它的實(shí)現(xiàn)有關(guān)了。
當(dāng)函數(shù)前面加new調(diào)用時(shí),會(huì)有以下事情完成:
一個(gè)全新的對(duì)象被創(chuàng)建
這個(gè)新的對(duì)象會(huì)被接入到原型鏈
這個(gè)新的對(duì)象被設(shè)置為函數(shù)調(diào)用的this綁定
除非函數(shù)有返回對(duì)象,否則這個(gè)被new調(diào)用的函數(shù)將自動(dòng)返回這個(gè)新的對(duì)象
主要我們要看的是第二點(diǎn),其他的會(huì)在this綁定的文章中講到。
所以在上面的例子中,調(diào)用new Foo()創(chuàng)建bar的時(shí)候,bar會(huì)得到一個(gè)內(nèi)部的[[Prototype]]鏈接,鏈接到Foo.prototype所指向的對(duì)象。
在“原型繼承”的例子代碼中var Baz = new Bar( "1", "obj 1" );也是使用了new來(lái)創(chuàng)建對(duì)象,從而使baz對(duì)象鏈接到bar.prototype上.
到目前為止,我們提到了2種方法來(lái)創(chuàng)建新對(duì)象并與其他對(duì)象關(guān)聯(lián):
Object.create()
函數(shù)前面加new調(diào)用
表面上看好像都可以達(dá)到我們的目的,但是第二種方法可能會(huì)有意想不到的副作用產(chǎn)生。假如說(shuō)Foo()這個(gè)函數(shù)還可以改變狀態(tài)或者向this添加數(shù)據(jù)屬性等,那么在對(duì)象在被創(chuàng)建的時(shí)候就會(huì)有這些我們可能本身并不需要的東西。
最后用一張圖來(lái)總結(jié)一下原型繼承:(圖來(lái)源:You-Dont-Know-JS)
從圖中可以看出,箭頭由右至左,由下至上。而[[Prototype]]機(jī)制,就是一種存在于對(duì)象上的內(nèi)部鏈接,指向另一個(gè)對(duì)象。
事實(shí)上,“原型繼承”這個(gè)詞很容易讓人產(chǎn)生誤會(huì),因?yàn)镴avaScript中沒(méi)有類,也就沒(méi)有繼承。實(shí)際上,Bar與Foo不能說(shuō)是繼承的關(guān)系,用準(zhǔn)確點(diǎn)的術(shù)語(yǔ)來(lái)說(shuō),是委托。所以接下來(lái)我們就要來(lái)了解一下委托了。
很簡(jiǎn)單,委托實(shí)際上就是原型鏈。比如說(shuō)新建對(duì)象a鏈接到對(duì)象b,a可以使用b的方法,也就是a委托了b(來(lái)實(shí)現(xiàn)它想要實(shí)現(xiàn)的效果)。這樣的話直接用Object.create就可以了,不需要再調(diào)用new函數(shù)了。var a = Object.create(a);
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93654.html
摘要:看完視頻初步認(rèn)識(shí)了一下,以及模塊化開(kāi)發(fā)的概念,在此做一下總結(jié)。所以應(yīng)該將功能抽象成模塊。并且非常耗性能解決辦法,在滾動(dòng)條正在運(yùn)動(dòng)或者已經(jīng)到達(dá)目的地,就不應(yīng)該執(zhí)行動(dòng)畫(huà)。 前言:在慕課網(wǎng)上跟著視頻《側(cè)邊工具欄開(kāi)發(fā)》做了一遍,用到了jquery操作DOM,其中,用requirejs管理模塊依賴,然后自定義了兩個(gè)模塊它們都依賴jquery,并且其中一個(gè)自定義模塊依賴另一個(gè),所以要暴露出接口。看...
摘要:最后舉兩個(gè)例子,回顧上面的內(nèi)容例一改變的是數(shù)組元素中屬性,由于創(chuàng)建的的指令,因此這里直接由指令更新對(duì)應(yīng)元素的內(nèi)容。 下面例子來(lái)自官網(wǎng),雖然看上去就比Hello World多了一個(gè)v-for,但是內(nèi)部多了好多的處理過(guò)程。但是這就是框架,只給你留下最美妙的東西,讓生活變得簡(jiǎn)單。 {{ todo.text }} ...
摘要:經(jīng)濟(jì)基礎(chǔ)決定上層建筑。以下暫不考慮嚴(yán)格模式。在全局執(zhí)行下,無(wú)論是否在嚴(yán)格模式下,指向全局對(duì)象。在其他函數(shù)內(nèi)部的箭頭函數(shù),這些箭頭函數(shù)的保留。當(dāng)一個(gè)用于在的事件監(jiān)聽(tīng)中,指向這個(gè)元素。 經(jīng)濟(jì)基礎(chǔ)決定上層建筑。 我來(lái)了 學(xué)習(xí),記錄,備忘。 感謝參考過(guò)的所有資料的作者。 嗯,能看源碼的就不要看文檔,能看英文文檔的就不要看中文文檔,能自己上手驗(yàn)證的就不要僅僅參考。請(qǐng)保持質(zhì)疑。深有所感。 t...
摘要:屬性這是每個(gè)對(duì)象都有的隱式原型屬性,指向了創(chuàng)建該對(duì)象的構(gòu)造函數(shù)的原型。 原型 在JavaScript中,有兩個(gè)原型,分別是 prototype 和 _proto_注:在ECMA-262第5版中管這個(gè) _proto_ 叫 [[Prototype]] prototype 屬性:這是一個(gè)顯式原型屬性,只有函數(shù)才擁有該屬性。_proto_ 屬性:這是每個(gè)對(duì)象都有的隱式原型屬性,指向了創(chuàng)建該對(duì)象...
摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過(guò)對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來(lái)。注意中,對(duì)象一定是通過(guò)類的實(shí)例化來(lái)的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
閱讀 962·2019-08-30 14:24
閱讀 1001·2019-08-30 14:13
閱讀 1807·2019-08-29 17:21
閱讀 2696·2019-08-29 13:44
閱讀 1667·2019-08-29 11:04
閱讀 453·2019-08-26 10:44
閱讀 2573·2019-08-23 14:04
閱讀 917·2019-08-23 12:08