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