欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript中this機制是如何真正工作的

 更新時間:2023年11月04日 14:24:15   投稿:yin  
JavaScript中this機制提供了更優(yōu)雅的方式來隱含地“傳遞”一個對象引用,導致更加干凈的API設計和更容易的復用,this既不是函數自身的引用,也不是函數詞法作用域的引用,this實際上是在函數被調用時建立的一個綁定,它指向什么是完全由函數被調用的調用點來決定的

this 不是編寫時綁定,而是運行時綁定。它依賴于函數調用的上下文條件。this 綁定與函數聲明的位置沒有任何關系,而與函數被調用的方式緊密相連。this 既不是函數自身的引用,也不是函數 詞法 作用域的引用。this 實際上是在函數被調用時建立的一個綁定,它指向 什么 是完全由函數被調用的調用點來決定的。

當一個函數被調用時,會建立一個稱為執(zhí)行環(huán)境的活動記錄。這個記錄包含函數是從何處(調用棧 —— call-stack)被調用的,函數是 如何 被調用的,被傳遞了什么參數等信息。這個記錄的屬性之一,就是在函數執(zhí)行期間將被使用的 this 引用。

為什么要用 this?

如果對于那些老練的 JavaScript 開發(fā)者來說 this 機制都是如此的令人費解,那么有人會問為什么這種機制會有用?它帶來的麻煩不是比好處多嗎?在講解 如何 有用之前,我們應當先來看看 為什么 有用。

讓我們試著展示一下 this 的動機和用途:

function identify() {
	return this.name.toUpperCase();
}

function speak() {
	var greeting = "Hello, I'm " + identify.call( this );
	console.log( greeting );
}

var me = {
	name: "Kyle"
};

var you = {
	name: "Reader"
};

identify.call( me ); // KYLE
identify.call( you ); // READER

speak.call( me ); // Hello, I'm KYLE
speak.call( you ); // Hello, I'm READER

如果這個代碼段 如何 工作讓你困惑,不要擔心!我們很快就會講解它。只是簡要地將這些問題放在旁邊,以便于我們可以更清晰的探究 為什么。

這個代碼片段允許 identify() 和 speak() 函數對多個 環(huán)境 對象(me 和 you)進行復用,而不是針對每個對象定義函數的分離版本。

與使用 this 相反地,你可以明確地將環(huán)境對象傳遞給 identify() 和 speak()。

function identify(context) {
	return context.name.toUpperCase();
}

function speak(context) {
	var greeting = "Hello, I'm " + identify( context );
	console.log( greeting );
}

identify( you ); // READER
speak( me ); // Hello, I'm KYLE

然而,this 機制提供了更優(yōu)雅的方式來隱含地“傳遞”一個對象引用,導致更加干凈的API設計和更容易的復用。

你的使用模式越復雜,你就會越清晰地看到:將執(zhí)行環(huán)境作為一個明確參數傳遞,通常比傳遞 this 執(zhí)行環(huán)境要亂。當我們探索對象和原型時,你將會看到一組可以自動引用恰當執(zhí)行環(huán)境對象的函數是多么有用。

this的困惑

我們很快就要開始講解 this 是如何 實際 工作的,但我們首先要摒棄一些誤解——它實際上 不是 如何工作的。

在開發(fā)者們用太過于字面的方式考慮“this”這個名字時就會產生困惑。這通常會產生兩種臆測,但都是不對的。

第一種常見的傾向是認為 this 指向函數自己。至少,這是一種語法上的合理推測。

為什么你想要在函數內部引用它自己?最常見的理由是遞歸(在函數內部調用它自己)這樣的情形,或者是一個在第一次被調用時會解除自己綁定的事件處理器。

初次接觸 JS 機制的開發(fā)者們通常認為,將函數作為一個對象(JavaScript 中所有的函數都是對象?。?,可以讓你在方法調用之間儲存 狀態(tài)(屬性中的值)。這當然是可能的,而且有一些有限的用處,但這本書的其余部分將會闡述許多其他的模式,提供比函數對象 更好 的地方來存儲狀態(tài)。

this的作用域

對 this 的含義第二常見的誤解,是它不知怎的指向了函數的作用域。這是一個刁鉆的問題,因為在某一種意義上它有正確的部分,而在另外一種意義上,它是嚴重的誤導。

明確地說,this 不會以任何方式指向函數的 詞法作用域。作用域好像是一個將所有可用標識符作為屬性的對象,這從內部來說是對的。但是 JavasScript 代碼不能訪問作用域“對象”。它是 引擎 的內部實現(xiàn)。

考慮下面代碼,它(失敗的)企圖跨越這個邊界,用 this 來隱含地引用函數的詞法作用域:

function foo() {
	var a = 2;
	this.bar();
}

function bar() {
	console.log( this.a );
}

foo(); //undefined

這個代碼段里不只有一個錯誤。雖然它看起來是在故意瞎搞,但你看到的這段代碼,提取自在公共社區(qū)的幫助論壇中被交換的真實代碼。真是難以想象對 this 的臆想是多么的誤導人。

首先,試圖通過 this.bar() 來引用 bar() 函數。它幾乎可以說是 碰巧 能夠工作,我們過一會兒再解釋它是 如何 工作的。調用 bar() 最自然的方式是省略開頭的 this.,而僅使用標識符進行詞法引用。

然而,寫下這段代碼的開發(fā)者試圖用 this 在 foo() 和 bar() 的詞法作用域間建立一座橋,使得bar() 可以訪問 foo()內部作用域的變量 a。這樣的橋是不可能的。 你不能使用 this 引用在詞法作用域中查找東西。這是不可能的。

每當你感覺自己正在試圖使用 this 來進行詞法作用域的查詢時,提醒你自己:這里沒有橋。

this調用點(Call-site)

為了理解 this 綁定,我們不得不理解調用點:函數在代碼中被調用的位置(不是被聲明的位置)。我們必須考察調用點來回答這個問題:這個 this 指向什么?

一般來說尋找調用點就是:“找到一個函數是在哪里被調用的”,但它不總是那么簡單,比如某些特定的編碼模式會使 真正的 調用點變得不那么明確。

考慮 調用棧(call-stack) (使我們到達當前執(zhí)行位置而被調用的所有方法的堆棧)是十分重要的。我們關心的調用點就位于當前執(zhí)行中的函數 之前 的調用。

我們來展示一下調用棧和調用點:

function baz() {
    // 調用棧是: `baz`
    // 我們的調用點是 global scope(全局作用域)

    console.log( "baz" );
    bar(); // <-- `bar` 的調用點
}

function bar() {
    // 調用棧是: `baz` -> `bar`
    // 我們的調用點位于 `baz`

    console.log( "bar" );
    foo(); // <-- `foo` 的 call-site
}

function foo() {
    // 調用棧是: `baz` -> `bar` -> `foo`
    // 我們的調用點位于 `bar`

    console.log( "foo" );
}

baz(); // <-- `baz` 的調用點

在分析代碼來尋找(從調用棧中)真正的調用點時要小心,因為它是影響 this 綁定的唯一因素。

注意: 你可以通過按順序觀察函數的調用鏈在你的大腦中建立調用棧的視圖,就像我們在上面代碼段中的注釋那樣。但是這很痛苦而且易錯。另一種觀察調用棧的方式是使用你的瀏覽器的調試工具。大多數現(xiàn)代的桌面瀏覽器都內建開發(fā)者工具,其中就包含 JS 調試器。在上面的代碼段中,你可以在調試工具中為 foo() 函數的第一行設置一個斷點,或者簡單的在這第一行上插入一個 debugger 語句。當你運行這個網頁時,調試工具將會停止在這個位置,并且向你展示一個到達這一行之前所有被調用過的函數的列表,這就是你的調用棧。所以,如果你想調查this 綁定,可以使用開發(fā)者工具取得調用棧,之后從上向下找到第二個記錄,那就是你真正的調用點。

到此這篇關于JavaScript中this機制是如何真正工作的的文章就介紹到這了,更多相關JavaScript中this關鍵字內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 原生JS實現(xiàn)手動輪播圖效果實例代碼

    原生JS實現(xiàn)手動輪播圖效果實例代碼

    手動輪播圖,為輪播圖中的一種,輪播圖主要有無縫輪播,手動輪播,延遲輪播,切換輪播等等,輪播圖主要用于展現(xiàn)圖片,新出商品,詞條,又能美觀網頁。給網頁中增加動態(tài)效果。接下來通過本文給大家分享原生JS實現(xiàn)手動輪播圖的實例代碼,一起看看吧
    2018-11-11
  • js、jquery實現(xiàn)列表模糊搜索功能過程解析

    js、jquery實現(xiàn)列表模糊搜索功能過程解析

    這篇文章主要介紹了js、jquery實現(xiàn)列表模糊搜索功能過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • IE與Firefox在JavaScript上的7個不同寫法小結

    IE與Firefox在JavaScript上的7個不同寫法小結

    盡管那需要用長串的、沉悶的不同分支代碼來應付不同瀏覽器的日子已經過去,偶爾還是有必要做一些簡單的區(qū)分和目標檢測來確保某塊代碼能在用戶的機器上正常運行。
    2009-09-09
  • 微信小程序如何實現(xiàn)在線客服功能

    微信小程序如何實現(xiàn)在線客服功能

    這篇文章主要介紹了微信小程序如何實現(xiàn)在線客服功能,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • layui實現(xiàn)左側菜單點擊右側內容區(qū)顯示

    layui實現(xiàn)左側菜單點擊右側內容區(qū)顯示

    這篇文章主要為大家詳細介紹了layui實現(xiàn)左側菜單點擊右側內容區(qū)顯示,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • 動態(tài)添加刪除表格行的js實現(xiàn)代碼

    動態(tài)添加刪除表格行的js實現(xiàn)代碼

    本篇文章主要是對動態(tài)添加刪除表格行的js實現(xiàn)代碼進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-02-02
  • JS中如何讓異步執(zhí)行的方法同步執(zhí)行

    JS中如何讓異步執(zhí)行的方法同步執(zhí)行

    在寫js的時候,很多時候都會遇到異步轉同步的問題,下面這篇文章主要給大家介紹了關于JS中如何讓異步執(zhí)行的方法同步執(zhí)行的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-04-04
  • 如何用js 實現(xiàn)依賴注入的思想,后端框架思想搬到前端來

    如何用js 實現(xiàn)依賴注入的思想,后端框架思想搬到前端來

    這篇文章主要介紹了js 實現(xiàn)依賴注入的思想,后端框架思想搬到前端來,需要的朋友可以參考下
    2015-08-08
  • javascript跨域刷新實現(xiàn)代碼

    javascript跨域刷新實現(xiàn)代碼

    在XX項目里面需要通過一個iframe去刷新同一窗口的另外一個iframe。一個超級簡單的處理,但我還在blog上記一記,有些看似簡單的東西,在真實項目應用中還是值得思考地方
    2011-01-01
  • Webpack?模塊加載動態(tài)引入機制源碼示例解析

    Webpack?模塊加載動態(tài)引入機制源碼示例解析

    這篇文章主要為大家介紹了Webpack?模塊加載動態(tài)引入機制源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09

最新評論