亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript中this機(jī)制是如何真正工作的

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

this 不是編寫時(shí)綁定,而是運(yùn)行時(shí)綁定。它依賴于函數(shù)調(diào)用的上下文條件。this 綁定與函數(shù)聲明的位置沒(méi)有任何關(guān)系,而與函數(shù)被調(diào)用的方式緊密相連。this 既不是函數(shù)自身的引用,也不是函數(shù) 詞法 作用域的引用。this 實(shí)際上是在函數(shù)被調(diào)用時(shí)建立的一個(gè)綁定,它指向 什么 是完全由函數(shù)被調(diào)用的調(diào)用點(diǎn)來(lái)決定的。

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

為什么要用 this

如果對(duì)于那些老練的 JavaScript 開(kāi)發(fā)者來(lái)說(shuō) this 機(jī)制都是如此的令人費(fèi)解,那么有人會(huì)問(wèn)為什么這種機(jī)制會(huì)有用?它帶來(lái)的麻煩不是比好處多嗎?在講解 如何 有用之前,我們應(yīng)當(dāng)先來(lái)看看 為什么 有用。

讓我們?cè)囍故疽幌?nbsp;this 的動(dòng)機(jī)和用途:

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

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

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

與使用 this 相反地,你可以明確地將環(huán)境對(duì)象傳遞給 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 機(jī)制提供了更優(yōu)雅的方式來(lái)隱含地“傳遞”一個(gè)對(duì)象引用,導(dǎo)致更加干凈的API設(shè)計(jì)和更容易的復(fù)用。

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

this的困惑

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

在開(kāi)發(fā)者們用太過(guò)于字面的方式考慮“this”這個(gè)名字時(shí)就會(huì)產(chǎn)生困惑。這通常會(huì)產(chǎn)生兩種臆測(cè),但都是不對(duì)的。

第一種常見(jiàn)的傾向是認(rèn)為 this 指向函數(shù)自己。至少,這是一種語(yǔ)法上的合理推測(cè)。

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

初次接觸 JS 機(jī)制的開(kāi)發(fā)者們通常認(rèn)為,將函數(shù)作為一個(gè)對(duì)象(JavaScript 中所有的函數(shù)都是對(duì)象!),可以讓你在方法調(diào)用之間儲(chǔ)存 狀態(tài)(屬性中的值)。這當(dāng)然是可能的,而且有一些有限的用處,但這本書(shū)的其余部分將會(huì)闡述許多其他的模式,提供比函數(shù)對(duì)象 更好 的地方來(lái)存儲(chǔ)狀態(tài)。

this的作用域

對(duì) this 的含義第二常見(jiàn)的誤解,是它不知怎的指向了函數(shù)的作用域。這是一個(gè)刁鉆的問(wèn)題,因?yàn)樵谀骋环N意義上它有正確的部分,而在另外一種意義上,它是嚴(yán)重的誤導(dǎo)。

明確地說(shuō),this 不會(huì)以任何方式指向函數(shù)的 詞法作用域。作用域好像是一個(gè)將所有可用標(biāo)識(shí)符作為屬性的對(duì)象,這從內(nèi)部來(lái)說(shuō)是對(duì)的。但是 JavasScript 代碼不能訪問(wèn)作用域“對(duì)象”。它是 引擎 的內(nèi)部實(shí)現(xiàn)。

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

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

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

foo(); //undefined

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

首先,試圖通過(guò) this.bar() 來(lái)引用 bar() 函數(shù)。它幾乎可以說(shuō)是 碰巧 能夠工作,我們過(guò)一會(huì)兒再解釋它是 如何 工作的。調(diào)用 bar() 最自然的方式是省略開(kāi)頭的 this.,而僅使用標(biāo)識(shí)符進(jìn)行詞法引用。

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

每當(dāng)你感覺(jué)自己正在試圖使用 this 來(lái)進(jìn)行詞法作用域的查詢時(shí),提醒你自己:這里沒(méi)有橋。

this調(diào)用點(diǎn)(Call-site)

為了理解 this 綁定,我們不得不理解調(diào)用點(diǎn):函數(shù)在代碼中被調(diào)用的位置(不是被聲明的位置)。我們必須考察調(diào)用點(diǎn)來(lái)回答這個(gè)問(wèn)題:這個(gè) this 指向什么?

一般來(lái)說(shuō)尋找調(diào)用點(diǎn)就是:“找到一個(gè)函數(shù)是在哪里被調(diào)用的”,但它不總是那么簡(jiǎn)單,比如某些特定的編碼模式會(huì)使 真正的 調(diào)用點(diǎn)變得不那么明確。

考慮 調(diào)用棧(call-stack) (使我們到達(dá)當(dāng)前執(zhí)行位置而被調(diào)用的所有方法的堆棧)是十分重要的。我們關(guān)心的調(diào)用點(diǎn)就位于當(dāng)前執(zhí)行中的函數(shù) 之前 的調(diào)用。

我們來(lái)展示一下調(diào)用棧和調(diào)用點(diǎn):

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

    console.log( "baz" );
    bar(); // <-- `bar` 的調(diào)用點(diǎn)
}

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

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

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

    console.log( "foo" );
}

baz(); // <-- `baz` 的調(diào)用點(diǎn)

在分析代碼來(lái)尋找(從調(diào)用棧中)真正的調(diào)用點(diǎn)時(shí)要小心,因?yàn)樗怯绊?nbsp;this 綁定的唯一因素。

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

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

相關(guān)文章

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

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

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

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

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

    IE與Firefox在JavaScript上的7個(gè)不同寫法小結(jié)

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

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

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

    layui實(shí)現(xiàn)左側(cè)菜單點(diǎn)擊右側(cè)內(nèi)容區(qū)顯示

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

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

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

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

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

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

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

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

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

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

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

最新評(píng)論