国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript繼承背后的場(chǎng)景-prototype,__proto__, [[prototype

鄒立鵬 / 2960人閱讀

摘要:實(shí)例可以通過代理來找到它,并用來檢測(cè)其構(gòu)造函數(shù)。經(jīng)典繼承圖這也是通過構(gòu)造函數(shù)來創(chuàng)建對(duì)象,但是在這一系列的對(duì)象和實(shí)例之間我們的焦點(diǎn)是放在原型鏈上。盡管,但構(gòu)造函數(shù)的屬性并不是對(duì)象自己的屬性,它實(shí)際上是通過尋找原型鏈獲得的,即所指向的地方。

繼承是面向?qū)ο缶幊陶Z言的一大核心功能點(diǎn),雖然JavaScript并不是一門真正意義上的面向?qū)ο蟮木幊陶Z言,但也通過某種手段實(shí)現(xiàn)了繼承這一功能,最常見的JavaScript繼承是通過原型鏈去實(shí)現(xiàn),這就涉及到了prototype、__proto__、[[prototype]]三者之間的關(guān)系了。


如上圖所示,理解JavaScript中的繼承的關(guān)鍵是要理解母雞如何產(chǎn)蛋的過程。

[[prototype]]、__proto__、prototype三者之間的聯(lián)系

每個(gè)對(duì)象都可以有另一個(gè)對(duì)象作為其原型。然后前一個(gè)對(duì)象繼承了它的所有原型屬性。對(duì)象通過內(nèi)部屬性[[Prototype]]指定其原型。由[[Prototype]]屬性連接的對(duì)象鏈稱為原型鏈。


為了理解基于原型的繼承是怎么樣的,我們先來看一個(gè)例子。

var proto = {
    describe: function () {
        return "name: "+this.name;
    }
};
var obj = {
    [[Prototype]]: proto,
    name: "obj"
};

> obj.describe
[Function]

> obj.describe()
"name: obj"

__proto__是Object.prototype對(duì)象的訪問者屬性。它暴露了訪問它的對(duì)象的內(nèi)部原型([[Prototype]])

function Foo(name) {
    this.name = name
    this.whoAmI = function () {
        return this.name
    }
}
var b = new Foo("b")
var a = new Foo("a")
b.say = function () {
    console.log(`Hi from ${this.whoAmI()}`)
}
console.log(a.__proto__ === Foo.prototype); // true
console.log(a.__proto__ === b.__proto__); // true


JavaScript引擎在對(duì)象b上添加了一個(gè)say方法,而不是在Foo原型對(duì)象(Foo.prototype)上

正如上圖中看到的那樣,a.__ proto__暴露了指向Foo.prototype對(duì)象的[[Prototype]]。同樣,b.__ proto__也指向與a.__ proto__相同的對(duì)象。

通過構(gòu)造函數(shù)來創(chuàng)建對(duì)象

除了通過指定模式創(chuàng)建對(duì)象之外,構(gòu)造函數(shù)還可以執(zhí)行另一個(gè)有用的操作 - 它會(huì)自動(dòng)為新創(chuàng)建的對(duì)象設(shè)置原型對(duì)象。此原型對(duì)象存儲(chǔ)在構(gòu)造函數(shù)的原型對(duì)象屬性中。

我們可以使用構(gòu)造函數(shù)用b對(duì)象重寫前面的例子。因此,對(duì)象a(原型)Foo.prototype的作用:

創(chuàng)建擁有原型對(duì)象屬性x及方法calculate()的一個(gè)Foo對(duì)象。

function Foo(y) {
  this.y = y;
}
Foo.prototype.x = 10;
Foo.prototype.calculate = function (z) {
  return this.x + this.y + z;
};

使用對(duì)象Foo創(chuàng)建一個(gè)b對(duì)象實(shí)例。

var b = new Foo(20);
b.calculate(30); // 60
console.log(
  b.__proto__ === Foo.prototype, // true
  b.__proto__.calculate === Foo.prototype.calculate // true
  b.__proto__.calculate === b.calculate, // true
  Foo === b.constructor, // true
  Foo === Foo.prototype.constructor, // true
);

正如上面打印出來的信息,對(duì)象b從Foo()繼承了方法calculate。“Foo.prototype”自動(dòng)創(chuàng)建一個(gè)特殊屬性“constructor”,它是對(duì)構(gòu)造函數(shù)本身的引用。實(shí)例b可以通過代理來找到它,并用來檢測(cè)其構(gòu)造函數(shù)。

JavaScript經(jīng)典繼承圖

這也是通過構(gòu)造函數(shù)來創(chuàng)建對(duì)象,但是在這一系列的對(duì)象和實(shí)例之間我們的焦點(diǎn)是放在原型鏈上。原型對(duì)象其實(shí)也是普通的對(duì)象,也有屬于它們自己的屬性。如果原型具有對(duì)其原型的非空引用,依此類推,則稱為原型鏈。

以下是JavaScript經(jīng)典繼承的圖表。構(gòu)造函數(shù)Foo只是虛構(gòu)類的類名。 foo對(duì)象是Foo的一個(gè)實(shí)例。


現(xiàn)在我們可以從圖中看到為什么當(dāng)我們從Dog類繼承Animal 時(shí),我們會(huì)這樣做:

function Dog() {} // the usual constructor function
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;

當(dāng)通過new操作符創(chuàng)建一個(gè)實(shí)例的時(shí)候,都發(fā)生了些什么:

注意Foo.prototype的原型(prototype)并不是來自原型鏈。Foo.prototype指向原型鏈中的某些位置,但Foo的這個(gè)原型屬性不是來自原型鏈。構(gòu)成原型鏈的是proto指向鏈,以及proto指向的對(duì)象。比如從foo .__ proto__,鏈接到到foo .__ proto . proto__,等等,直到達(dá)到null(也就是咱們常說的原型鏈的頂部是null)。

proto and prototype的關(guān)系:

JavaScript的經(jīng)典繼承就像這樣:我是一個(gè)構(gòu)造函數(shù),我只是一個(gè)函數(shù),我持有一個(gè)原型引用,每當(dāng)調(diào)用foo = new Foo()時(shí),我會(huì)讓foo .__ proto__指向我的原型對(duì)象。所以,F(xiàn)oo.prototype 與 obj.__proto__是兩個(gè)不同的概念。Foo.prototype指示,當(dāng)創(chuàng)建Foo的對(duì)象時(shí),這是新對(duì)象的原型鏈應(yīng)該指向的點(diǎn) - 也就是說,foo .__ proto__應(yīng)該指向Foo.prototype指向的位置。

如果需要添加一個(gè)方法怎么辦?

如果woofie這個(gè)對(duì)象沒有movie方法,它將通過原型鏈去尋找,就像任何原型繼承場(chǎng)景一樣,首先這個(gè)對(duì)象通過woofie.__proto__,它與Dog.prototype所指的對(duì)象相同。如果move方法不是這個(gè)對(duì)象的一個(gè)屬性(意味著Dog這個(gè)類并沒有move這個(gè)方法),則在原型鏈中上升一級(jí)(去原型鏈上尋找),即woofie .__ proto . proto__,或者與Animal.prototype相同。

Animal.prototype.move = function() { ... };


*盡管foo.constructor === Foo,但構(gòu)造函數(shù)的屬性并不是foo對(duì)象自己的屬性,它實(shí)際上是通過尋找原型鏈獲得的,即foo .__ proto__所指向的地方。對(duì)Function.constructor也是一樣。

當(dāng)我們看到Constructor.prototype,foo .__ proto__,F(xiàn)oo.prototype.constructor時(shí),該圖可能很復(fù)雜,有時(shí)會(huì)令人困惑。

要驗(yàn)證圖表,請(qǐng)注意,即使foo.constructor將顯示一個(gè)值,foo.constructor也不是foo自己的屬性,而是通過跟蹤原型鏈獲得的,因?yàn)榭梢詼贤ㄟ^foo.hasOwnProperty(“constructor”)來進(jìn)行驗(yàn)證。
*

總結(jié)

[[Prototype]]:對(duì)象通過其內(nèi)部屬性指定的原型對(duì)象

proto :創(chuàng)建的對(duì)象實(shí)例所擁有的內(nèi)部屬性,在語言層面可以直接訪問[[Prototype]]

prototype:prototype是在使用new操作符創(chuàng)建對(duì)象時(shí)用于構(gòu)建__proto__的對(duì)象,在實(shí)例化的對(duì)象上(或其他對(duì)象)不可使用,僅在構(gòu)造函數(shù)上使用,因?yàn)樗菑腇untion和Object上復(fù)制的。而__proto__隨處可用

    ( new Foo ).__proto__ === Foo.prototype  //true
    ( new Foo ).prototype === undefined      //true
    
參考資料

http://speakingjs.com/es5/ind...

http://www.javascripttutorial...

http://stackoverflow.com/ques...

http://dmitrysoshnikov.com/ec...

https://www.quora.com/What-is...

http://www.jisaacks.com/proto...

http://kenneth-kin-lum.blogsp...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/105828.html

相關(guān)文章

  • 深入理解 JavaScript class

    摘要:在規(guī)范中,引入了的概念。使用中的聲明一個(gè)類,是非常簡單的事。中面向?qū)ο髮?shí)例化的背后原理,實(shí)際上就是原型對(duì)象。與區(qū)別理解上述原理后,還需要注意與屬性的區(qū)別。實(shí)際上,在中,類繼承的本質(zhì)依舊是原型對(duì)象。 在 ES6 規(guī)范中,引入了 class 的概念。使得 JS 開發(fā)者終于告別了,直接使用原型對(duì)象模仿面向?qū)ο笾械念惡皖惱^承時(shí)代。 但是JS 中并沒有一個(gè)真正的 class 原始類型, clas...

    Vicky 評(píng)論0 收藏0
  • Lodash 嚴(yán)重安全漏洞背后 你不得不知道 JavaScript 知識(shí)

    摘要:可能有信息敏感的同學(xué)已經(jīng)了解到庫爆出嚴(yán)重安全漏洞,波及萬項(xiàng)目。以此為例,可見這次漏洞算是比較嚴(yán)重了。此外,凍結(jié)一個(gè)對(duì)象后該對(duì)象的原型也不能被修改。 摘要: 詳解原型污染。 原文:Lodash 嚴(yán)重安全漏洞背后 你不得不知道的 JavaScript 知識(shí) 作者:Lucas HC Fundebug經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所有。 可能有信息敏感的同學(xué)已經(jīng)了解到:Lodash 庫爆出嚴(yán)...

    YorkChen 評(píng)論0 收藏0
  • 最新:Lodash 嚴(yán)重安全漏洞背后你不得不知道 JavaScript 知識(shí)

    摘要:可能有信息敏感的同學(xué)已經(jīng)了解到庫爆出嚴(yán)重安全漏洞,波及萬項(xiàng)目。以此為例,可見這次漏洞算是比較嚴(yán)重了。此外,凍結(jié)一個(gè)對(duì)象后該對(duì)象的原型也不能被修改。使用數(shù)據(jù)結(jié)構(gòu),不會(huì)存在原型污染狀況。 可能有信息敏感的同學(xué)已經(jīng)了解到:Lodash 庫爆出嚴(yán)重安全漏洞,波及 400萬+ 項(xiàng)目。這個(gè)漏洞使得 lodash 連夜發(fā)版以解決潛在問題,并強(qiáng)烈建議開發(fā)者升級(jí)版本。 我們?cè)诿χ礋狒[或者升級(jí)版本的同時(shí)...

    Integ 評(píng)論0 收藏0
  • 深入 JavaScript 原型繼承原理——babel 編譯碼解讀

    摘要:目錄無繼承簡單的字段聲明無繼承簡單的方法聲明簡單繼承一層繼承字段覆蓋無繼承靜態(tài)函數(shù)無繼承靜態(tài)變量神秘的類無繼承簡單的字段聲明先來看個(gè)最簡單的例子,我們僅僅使用了關(guān)鍵字并定義了一個(gè)變量最后編譯出來的代碼如下。無繼承靜態(tài)變量還有個(gè)小例子。 在[上一篇文章][]中,我們提到 ES6 的 class 語法糖是個(gè)近乎完美的方案,并且講解了實(shí)現(xiàn)繼承的許多內(nèi)部機(jī)制,如 prototype/__pro...

    stdying 評(píng)論0 收藏0
  • js繼承從入門到理解

    摘要:問題修改實(shí)例的,即修改了構(gòu)造函數(shù)的原型對(duì)象的共享屬性到此處,涉及到的內(nèi)容大家可以再回頭捋一遍,理解了就會(huì)覺得醍醐灌頂。 開場(chǎng)白 大三下學(xué)期結(jié)束時(shí)候,一個(gè)人跑到帝都來參加各廠的面試,免不了的面試過程中經(jīng)常被問到的問題就是JS中如何實(shí)現(xiàn)繼承,當(dāng)時(shí)的自己也是背熟了實(shí)現(xiàn)繼承的各種方法,回過頭來想想?yún)s不知道__proto__是什么,prototype是什么,以及各種繼承方法的優(yōu)點(diǎn)和缺點(diǎn),想必有好...

    不知名網(wǎng)友 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<