亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

【譯】this 是什么?JavaScript 對象的內(nèi)部工作原理

Hwg / 3114人閱讀

摘要:關(guān)鍵字會實例化一個新的對象實例,并在執(zhí)行構(gòu)造函數(shù)時將指向該實例。原文鏈接譯是什么對象的內(nèi)部工作原理

原文鏈接:What is this? The Inner Workings of JavaScript Objects (需要梯子)

原文作者:Eric Elliott

譯文永久鏈接:【譯】什么是 this?JavaScript 對象的內(nèi)部工作原理

譯者:士心

翻譯目的:函數(shù)動態(tài)綁定 this 的特性,經(jīng)常讓開發(fā)者感到頭疼,這篇文章能幫助梳理概念

JavaScript 是一種支持面向?qū)ο缶幊毯蛣討B(tài)綁定的多范式語言。動態(tài)綁定是其一個強大的特性,它允許 JavaScript 代碼在運行時更改 this,但是這一強大而且靈活的特性卻會給開發(fā)者帶來一些困惑,這些困惑集中在 JavaScript 代碼運行時的表現(xiàn)上。

動態(tài)綁定(Dynamic Binding)

動態(tài)綁定指的是在運行時才確定調(diào)用函數(shù)的方式,而不是更早的編譯階段。JavaScript 通過 this 和原型鏈來體現(xiàn)動態(tài)綁定。也就是說,函數(shù)內(nèi)部的 this 是在運行時確定,并且定義函數(shù)的方式不同,確定 this 的規(guī)則也不同。

先來玩?zhèn)€游戲。這個游戲叫 “this 是什么?”

const a = {
  a: "a"
};
const obj = {
  getThis: () => this,
  getThis2 () {
    return this;
  }
};
obj.getThis3 = obj.getThis.bind(obj);
obj.getThis4 = obj.getThis2.bind(obj);
const answers = [
  obj.getThis(),
  obj.getThis.call(a),
  obj.getThis2(),
  obj.getThis2.call(a),
  obj.getThis3(),
  obj.getThis3.call(a),
  obj.getThis4(),
  obj.getThis4.call(a)
];

在繼續(xù)之前,請先寫下你的答案。完成后,console.log()你的答案,你答對了嗎?

譯者注:本文的示例需要運行在 ES6 Module 下才符合文章所說的結(jié)果,你可以在 HTML 頁面中指定腳本標簽類型 ... 讓代碼運行在 ES6 Module 下。如果你將代碼直接復制到瀏覽器控制臺運行,下文說的 undefined 實際上是 window。

讓我們從第一個結(jié)果開始。obj.getThis() 返回 undefined,但為什么呢?箭頭函數(shù)永遠不會綁定屬于自己的 this,它們的 this 總是綁定在定義時所在的作用域上。本例中的定義時所在的作用域,就是 ES6 模塊的根作用域,這里的 thisundefined。因為相同的原因,obj.getThis.call(a) 同樣也是 undefined。對于箭頭函數(shù),它的 this 不能被重新分配賦值,即使使用 .call().bind(),它的 this 總是綁定在定義時所在的作用域上,而不會指向運行時所在的作用域。

obj.getThis2() 通過一般的函數(shù)調(diào)用獲取其綁定。如果函數(shù)之前沒有綁定 this(就是說,它不是箭頭函數(shù)),那該函數(shù)就可以擁有自己的 this 綁定,具體綁定到使用 .[] 調(diào)用該方法的對象上。

obj.getThis2.call(a) 做了點小動作,call() 方法提供給定的 this 值和可選參數(shù)調(diào)用函數(shù)。換句話說,函數(shù)從 .call() 參數(shù)獲取 this 的綁定,因此 obj.getThis2.call(a) 返回 a 對象。

使用 obj.getThis3 = obj.getThis.bind(obj);,我們嘗試綁定一個箭頭函數(shù),前面我們已經(jīng)討論過綁定箭頭函數(shù)是不起作用的,所以 obj.getThis3()obj.getThis3.call(a) 都得到 undefined。

我們可以綁定一般的函數(shù),所以 obj.getThis4() 按預期返回 obj,因為它已經(jīng)使用 obj.getThis4 = obj.getThis2.bind(obj); 綁定了。而 obj.getThis4.call(a) 遵從第一個的綁定,所以返回 obj 而不是 a。

加大難度(Curve Ball)

同樣的挑戰(zhàn),不過這一次,使用到了 class 的公共字段語法(public fields syntax) (寫這篇文章的時候,該語法提案處于 Stage3 階段。Chrome 和 @babel/plugin-proposal-class-properties 已經(jīng)支持):

譯者注:公共字段語法(public fields syntax),如果不知道是什么的話,可以看阮一峰 ES6 | Class 的基本語法: 實例屬性的新寫法
class Obj {
  getThis = () => this
  getThis2 () {
    return this;
  }
}
const obj2 = new Obj();
obj2.getThis3 = obj2.getThis.bind(obj2);
obj2.getThis4 = obj2.getThis2.bind(obj2);
const answers2 = [
  obj2.getThis(),
  obj2.getThis.call(a),
  obj2.getThis2(),
  obj2.getThis2.call(a),
  obj2.getThis3(),
  obj2.getThis3.call(a),
  obj2.getThis4(),
  obj2.getThis4.call(a)
];

在繼續(xù)之前寫下你的答案。

準備好了?

除了 obj2.getThis2.call(a) 返回 a 對象外,其它都返回對象實例。箭頭函數(shù)的 this 仍然綁定在定義時所在的作用域上,區(qū)別在于定義時所在作用域的 this 已然不是 undefined。這段代碼的底層,會將類的屬性賦值編譯成:

class Obj {
  constructor() {
    this.getThis = () => this;
  }
...

也就是說,箭頭函數(shù)是在構(gòu)造函數(shù)(constructor)的上下文中定義的。由于它是一個類,創(chuàng)建實例的唯一方法是使用 new 關(guān)鍵字(省略 new 會拋出錯誤)。

new 關(guān)鍵字會實例化一個新的對象實例,并在執(zhí)行構(gòu)造函數(shù)時將 this 指向該實例。這種行為,加上我們上面已經(jīng)提到的其他行為,就能解釋清楚結(jié)果。

總結(jié)

你做得怎樣?有沒有做對呢?理解了 this 的表現(xiàn)行為,在調(diào)試棘手的問題時能節(jié)省大量時間。如果你做錯了任意一道,那你需要多加練習。研究上面這些例子,然后回來再做一次,直到你都能做對,并向其他人解釋為什么這些方法會返回這些值。

如果這些題比你想象的要難,你并不是一個人。針對這個主題,我已經(jīng)問過了不少開發(fā)者,我認為到目前為止只有一位開發(fā)人員掌握了。

加上類和箭頭函數(shù)的行為,會使 .call(),. bind().apply() 的動態(tài)綁定開始變得復雜。請記住,箭頭函數(shù)總是將 this 綁定在定義時所在的作用域上,第二個例子 class 中的 this 實際綁定在執(zhí)行構(gòu)造函數(shù)時的作用域上。如果你還有疑問,請記住使用 debugger 工具來驗證是否符合你的想法。

還要記住,在JavaScript中,即使不用 this,你也可以做很多事情。根據(jù)我的經(jīng)驗,幾乎任何東西都可以使用純函數(shù)重新實現(xiàn),純函數(shù)接收所有傳遞給它們的顯式參數(shù)(你可以將 this 看成是可變的隱式參數(shù))。封裝在純函數(shù)中的邏輯具有確定性,這使得它更易于測試,并且沒有副作用。這意味著與操作 this 不同,你不可能破壞其他任何東西。而每當你修改 this 時,依賴于 this 的行為就可能被破壞。

也就是說,this 有時很有用,例如:在大量對象之間共享方法。即使在函數(shù)式編程中,this 對于訪問其他對象上的函數(shù),以實現(xiàn)在現(xiàn)有函數(shù)之上構(gòu)建新函數(shù)是很有用的,例如:.flatMap() 可以通過組合 this.map()this.constructor.of() 來實現(xiàn)。

如果你喜歡這篇文章,請關(guān)注我,我會持續(xù)輸出更多原創(chuàng)且高質(zhì)量的內(nèi)容。

原文鏈接:【譯】this 是什么?JavaScript 對象的內(nèi)部工作原理

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/103801.html

相關(guān)文章

  • JavaScript面試問題:事件委托和this

    摘要:主題來自于的典型面試問題列表。有多種方法來處理事件委托。這種方法的缺點是父容器的偵聽器可能需要檢查事件來選擇正確的操作,而元素本身不會是一個監(jiān)聽器。 showImg(http://fw008950-flywheel.netdna-ssl.com/wp-content/uploads/2014/11/Get-Hired-Fast-How-to-Job-Search-Classifieds...

    浠ラ箍 評論0 收藏0
  • JavaScript 工作原理之二-如何在 V8 引擎中書寫最優(yōu)代碼 5 條小技巧()

    摘要:本章將會深入谷歌引擎的內(nèi)部結(jié)構(gòu)。一個引擎可以用標準解釋程序或者即時編譯器來實現(xiàn),即時編譯器即以某種形式把解釋為字節(jié)碼。引擎的由來引擎是由谷歌開源并以語言編寫。注意到?jīng)]有使用中間字節(jié)碼來表示,這樣就不需要解釋器了。 原文請查閱這里,略有刪減。 本系列持續(xù)更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第二章。 本章將會深入谷歌 V8 引擎的內(nèi)部結(jié)構(gòu)。我們也會...

    PingCAP 評論0 收藏0
  • []JavaScript如何工作:內(nèi)存管理以及如何處理四種常見內(nèi)存泄漏

    摘要:是如何工作的內(nèi)存管理以及如何處理四種常見的內(nèi)存泄漏原文譯者幾個禮拜之前我們開始一系列對于以及其本質(zhì)工作原理的深入挖掘我們認為通過了解的構(gòu)建方式以及它們是如何共同合作的,你就能夠?qū)懗龈玫拇a以及應用。 JavaScript是如何工作的:內(nèi)存管理以及如何處理四種常見的內(nèi)存泄漏 原文:How JavaScript works: memory management + how to han...

    tianren124 評論0 收藏0
  • 】理解JavaScript:閉包

    摘要:當面試中讓我解釋一下閉包時我懵逼了。這個解釋開始可能有點晦澀,讓我們抽絲剝繭摘下閉包的真面目。此文不詳述作用域有專門的主題闡述,不過作用域是理解閉包原理的基礎。這才是閉包的真正便利之處。閉包使用不當就會很坑。 原文鏈接 為什么深度學習JavaScript? JavaScript如今是最流行的編程語言之一。它運行在瀏覽器、服務器、移動設備、桌面應用,也可能包括冰箱。無需我舉其他再多不相干...

    岳光 評論0 收藏0
  • JavaScript 工作原理之一-引擎,運行時,調(diào)用堆棧()

    摘要:本章會對語言引擎,運行時,調(diào)用棧做一個概述。調(diào)用棧只是一個單線程的編程語言,這意味著它只有一個調(diào)用棧。查看如下代碼當引擎開始執(zhí)行這段代碼的時候,調(diào)用棧會被清空。之后,產(chǎn)生如下步驟調(diào)用棧中的每個入口被稱為堆棧結(jié)構(gòu)。 原文請查閱這里,本文采用知識共享署名 4.0 國際許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請查閱這里。 這是 JavaScript 工作原...

    Betta 評論0 收藏0

發(fā)表評論

0條評論

Hwg

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<