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

資訊專欄INFORMATION COLUMN

理解JavaScript的核心知識點:This

TerryCai / 2770人閱讀

摘要:關鍵字計算為當前執行上下文的屬性的值。毫無疑問它將指向了這個前置的對象。構造函數也是同理。嚴格模式無論調用位置,只取顯式給定的上下文綁定的,通過方法傳入的第一參數,否則是。其實并不屬于特殊規則,是由于各種事件監聽定義方式本身造成的。

thisJavaScript 中非常重要且使用最廣的一個關鍵字,它的值指向了一個對象的引用。這個引用的結果非常容易引起開發者的誤判,所以必須對這個關鍵字刨根問底。

執行上下文:Execution Context

在深入了解 this 對象之前先介紹另一個概念:執行上下文。

沒錯,執行上下文與 this 在本質上是兩個概念,或者說它們指代的范疇有差異,想要準確認識 this,就得先把它們區分開。

可以把執行上下文想象為一個容器,其中包含了一句句待執行的代碼。代碼在這個容器中有上下行兩條路線,是由某一些特殊代碼所觸發(如函數),上行路線跳入了一個新的容器,開始在新容器中執行另一些代碼,本容器中的后續代碼被暫時中斷;如果新容器中還有代碼會觸發上行路線,就繼續往上增加新容器,并交出控制權,層層疊加,形成了一個從底往上形式的疊羅漢,這就是 JavaScript 運行時的執行上下文棧。

執行上下文這一抽象概念本身包含了更多有關 JavaScript 這門語言的內部機制,對于語言使用者來說是不透明的,其中與運行前的編譯規則有很大關聯,并被包含到整個程序運行前的初始化過程中,與詞法作用域的變量解析規則相配合,將這些靜態解析后的變量帶入運行時的環境,所以它是程序運行時的關鍵內部組件或者說容器,而 JavaScript 將對執行上下文的引用提供給程序開發者的唯一入口就是 this,它得以訪問被編譯后帶入到某個執行上下文運行環境中的變量。this 指代的其實只是內部抽象的執行上下文向用戶所開放的那一部分,其實體是一個對象,綁定了許多編譯后的變量。

以下是一段關于執行上下文精辟的總結:

An execution context is purely a specification mechanism and need not correspond to any particular artefact of an ECMAScript implementation. It is impossible for ECMAScript code to directly access or observe an execution context.

翻譯:執行上下文純粹是一種規范機制,它不需要與基于 ECMAScript 規范的任何特定擴展實現對應。ECMAScript 代碼無法直接訪問或觀察執行上下文。

關于This對象:What"s This

我將官方文檔和一些別的文章里的說明稍加梳理,可以從以下段落中較為清晰地看出 this 的本質:

First, know that all functions in JavaScript have properties, just as objects have properties. And when a function executes, it gets the this property—a variable with the value of the object that invokes the function where this is used.

The this keyword evaluates to the value of the ThisBinding of the current execution context.

The abstract operation GetThisEnvironment finds the Environment Record that currently supplies the binding of the keyword this

this is not assigned a value until an object invokes the function where this is defined.

翻譯:

首先,要知道 JavaScript 中所有的函數與對象一樣都擁有屬性。當一個函數執行時,它得到 this 屬性——一個指向調用函數的對象的變量。

this 關鍵字計算為當前執行上下文的 ThisBinding 屬性的值。

GetThisEnvironment 抽象運算查找當前提供 this 關鍵字的綁定的環境記錄。

在對象調用了定義了 this 的函數之前,this 不會被賦值。

由此可得出關于 this 的完全定義:this 是在程序運行時,通過語言內部抽象操作在執行上下文中動態計算得到的,指向調用使用了其的函數的對象的變量。

執行上下文 vs. This關鍵字:Execution Context vs. This Keyword

執行上下文和 this 關鍵字的關系與潛意識相對于意識的關系類似,執行上下文是冰山下深邃龐大而不可窺探的秘地,而 this 只將其一個小部分顯露出來。由于 JavaScript 是面向對象的編程語言,所以執行上下文其實質相當于一個對象,this 指向了它向開發者開放了的一系列屬性集合的對象,因而我把 this 叫做執行上下文的引用對象。

This因何而來:Why This

JavaScript 在編寫初始借鑒了JAVAC 語言的特性,即便本質上不同,但還是把這個如同慣例般存在的 this 拿了過來。使用 this 的原因其實很簡單:

首先,我們時常無法得知調用了函數的對象的名稱,并且有時候根本就沒有名稱可以用來引用調用對象。這是一個迫切的原因,因為我們在開發時必定會遇到需要引用調用函數的對象的場景。

其次,避免重復指代,就像我們經常使用第三人稱來指代前文的主體一樣,作為程序員大家當然很樂意使用一個快捷方式來避免機械重復一些不必要的代碼,這也是“語言”這一重要產品的特性。

最后,它提供給我們實現高級功能的可能性,我們可以通過 this 動態對于執行上下文的指代而實現程序的復用性和擴展。

This的判斷規則:Rules of This

this 的根源進行深入探究的目的就是為了在開發中對自己所使用的 this 關鍵字指代的對象進行準確的判定,它就是一個變量,所以當我們使用它的時候,必須清晰地知道它的值到底是什么。

一般來說,我們可以通過確定是哪個對象擁有所調用的函數來確定其 this 的指向。這是由于 this 的綁定值是在函數調用的時候才賦予的,要看函數在哪個上下文對象中調用,但有時候這不是僅用肉眼就能觀察出來的。

此外還要嚴肅聲明一下,雖然在之前下定義的時候將 this 的概念明確地劃分到了運行階段,但由于它作為一個變量的特性,是可以改變引用值的,它的值的計算與詞法規則還是息息相關,得將編譯和運行時兩個階段結合起來,總結出關于判斷 this 綁定值的基本原則。

this 關鍵字綁定的操作是在語言內核機制的運行時里執行的,由于無法去探索其內部,只能通過官方文檔中給出的一系列描述程序來得知其如何判斷,可以梳理出函數調用的內部過程中對 this 的綁定計算的依據:

前置知識 1: 內部機制創建執行上下文、初始化函數所屬領域和創建相關環境記錄

在函數被真正執行之前,內部機制會執行創建擁有函數的領域、創建執行上下文、移交當前執行上下文控制權、創建環境記錄、環境記錄對象參數的綁定等一系列操作,為程序運行做編譯準備。在將函數推入執行棧頂層的時候,對其上下文的歸屬有以下的判斷過程,此處與一個新的概念領域有關:

如果領域中的屬性 this 返回了一個對象,就將內部屬性 thisValue 設置為以此對象為基礎按照規格創建的 js 對象,否則 thisValue 綁定值為 undefined,表明領域的全局對象(本地全局對象)將設置為全局對象(程序全局對象)。

這里在新規范里出現的一個概念領域取代了之前版本中簡單的作用域的概念,由于實現了模塊化等其他新特性,所以作用域的概念可以相當于擴展成了現在的領域,它下屬了其他幾個環境記錄,其中變量的綁定分別在不同環境記錄中,這里就不做深入解釋了。

領域中比較重要的屬性是領域中的全局對象,這與程序運行時的全局對象的概念要加以區別,所以可以把領域中的全局對象看作是本地全局變量,其實也就是函數所屬的上下文對象,它的值就是在剛才的以上的判斷中確定的,如果沒有這個前置對象,就會把全局對象設置為本地全局對象的值。

前置知識 2: 內部機制創建函數

內部機制在詞法分析階段會通過函數的定義方式向創建函數操作傳入幾種不同類型的函數類型:NormalArrowMethod,相對應的是普通函數、箭頭函數、作為對象方法的函數。同時在這一步還傳入指定代碼嚴格模式的參數 strict。然后進行函數的初始化的。

方式 1: 內部機制初始化普通函數

內部機制在這一步會設置函數的一個重要屬性 ThisMode 的值,它是決定 this 綁定值的依據,它的值是根據上一步傳入的參數來判斷的,依次執行一下三條判斷分支:

函數類型為 Arrow:將 ThisMode 賦值為 lexical ,這個值在計算 this 綁定時將按照詞法作用域的規則來賦值,也就是說 this 的值與定義函數的詞法作用域中的 this 相一致。

代碼模式為 strict :將 ThisMode 賦值 strict,按照這個值計算 this 綁定時只會將顯式傳入的上下文對象綁定給 this

非以上兩種條件:將 ThisMode 賦值 global,被設置為 global 之后,函數在運行階段被調用時,this 的值就會指向全局對象。

方式 2: 內部機制創建對象方法函數

作為對象屬性的方法是另外來計算 this 的,只有在作為對象方法被調用的函數,在內部創建函數時才會傳入 Method 值。毫無疑問它將 this 指向了這個前置的對象。構造函數也是同理。

總結一下對一般使用到的函數的判斷規則如下:

箭頭函數:無論調用位置,取它詞法定義處的外層上下文中綁定的 this,沒有中間本地對象存在時總是能夠取到全局對象。

嚴格模式:無論調用位置,只取顯式給定的上下文綁定的 this,通過 call()apply()bind() 方法傳入的第一參數,否則是 undefined

new 關鍵字調用的構造器函數:無論調用位置,this 必為在內部創建的新的實例對象

顯式綁定上下文對象的普通函數:無論調用位置,this 必為傳入的上下文對象

方法函數:屬于隱式綁定,無論詞法定義位置,實際情況視調用處而定:

直接調用時:this 為前置上下文對象

作為被引用值時:this 為調用時的上下文對象,在其他對象中引用 this 就是這個調用它的對象;被全局變量引用,this 就是全局對象。

普通函數:無論詞法定義位置,視調用處而定,其實質在內存都都是被作為引用值調用的,所以 this 都指向全局對象,嚴格模式規則優先。

另外關于事件造成的一些 this 誤解可以參考The this keyword這篇文章。其實并不屬于特殊規則,是由于各種事件監聽定義方式本身造成的。

在實際開發中可以參考《You Don"t Know JS》里關于 this 的綁定規則和優先級的章節Nothing But Rules。在這套基礎通用規則之外,箭頭函數利用了另一套方式來判斷 this 的綁定值,這篇文章里也有詳盡的敘述。

參考文獻:Reference

The ECMAScript 9.0 Standard

Executable Code and Execution Contexts

The ECMAScript 5.1 Standard

The this Keyword

MDN web docs: this

You Don"t Know JS: this & object prototypes

Chapter 1: this Or That?

Chapter 2: this All Makes Sense Now!

Understanding the "this" keyword in JavaScript

The this keyword

StackOverflow: How does the “this” keyword work?

Scope In JavaScript

Understand JavaScript’s “this” With Clarity, and Master It

JavaScript 的 this 原理

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/103655.html

相關文章

  • 理解JavaScript核心識點:作用域

    摘要:也毫不例外,但在中作用域的特性與其他高級語言稍有不同,這是很多學習者久久難以理清的一個核心知識點。主要使用的是函數作用域。 關于作用域:About Scope 作用域是程序設計里的基礎特性,是作用域使得程序運行時可以使用變量存儲值、記錄和改變程序的狀態。JavaScript 也毫不例外,但在 JavaScript 中作用域的特性與其他高級語言稍有不同,這是很多學習者久久難以理清的一個核...

    HelKyle 評論0 收藏0
  • 理解javascript核心識點

    摘要:作用域鏈的作用就是做標示符解析。事件循環還有個明顯的特點單線程。早期都是用作開發,單線程可以比較好當規避同步問題,降低了開發門檻。單線程需要解決的是效率問題,里的解決思想是異步非阻塞。 0、前言 本人在大學時非常癡迷java,認為java就是世界上最好的語言,偶爾在項目中會用到一些javascript,但基本沒放在眼里。較全面的接觸javascript是在實習的時候,通過這次的了解發現...

    laznrbfe 評論0 收藏0
  • 33 個 js 核心概念(三):值類型與引用類型

    摘要:它們的區別之一就是在計算機中的存儲方式不同基本類型數據是將變量名及值存儲在變量對象中,而引用類型的數據是將變量名和地址存儲在變量對象中,真正的值是存儲在堆內存中。 showImg(https://segmentfault.com/img/remote/1460000017151449); 說點別的 這是《關于 JavaScript 你必須要知道的 33 個概念 》系列的第三篇文章,今天...

    everfight 評論0 收藏0
  • 十分鐘快速了解《你不知道 JavaScript》(上卷)

    摘要:最近剛剛看完了你不知道的上卷,對有了更進一步的了解。你不知道的上卷由兩部分組成,第一部分是作用域和閉包,第二部分是和對象原型。附錄詞法這一章并沒有說明機制,只是介紹了中的箭頭函數引入的行為詞法。第章混合對象類類理論類的機制類的繼承混入。 最近剛剛看完了《你不知道的 JavaScript》上卷,對 JavaScript 有了更進一步的了解。 《你不知道的 JavaScript》上卷由兩部...

    趙春朋 評論0 收藏0
  • JavaScript面向對象程序設計

    摘要:目錄導語理解對象和面向對象的程序設計創建對象的方式的繼承機制原型對象原型鏈與原型對象相關的方法小結導語前面的系列文章,基本把的核心知識點的基本語法標準庫等章節講解完本章開始進入核心知識點的高級部分面向對象的程序設計,這一部分的內容將會對對象 目錄 導語 1.理解對象和面向對象的程序設計 2.創建對象的方式 3.JavaScript的繼承機制 3.1 原型對象 3.2 原型鏈 3.3 與...

    gitmilk 評論0 收藏0

發表評論

0條評論

TerryCai

|高級講師

TA的文章

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