摘要:本文不是標準的中文翻譯,也不是的入門教程,本文雖然以的常見問題切入,但并不適合想要快速了解這些問題的人才是快速了解問題的正解。盡量以英文原版為基礎,為了流暢,可能會使用某些名詞的中文翻譯,但會將匹配的英文名詞以此種樣式中出現一次以避免誤解。
簡單易懂的ECMA規范導讀1 序
最近混SF,恰巧又逢工作方面有了NodeJS的機會,迫切地有教別人怎么寫JS的需求,
我發現JS這個東西其實真沒那么容易理解。
為了加深和糾正自己對JS的理解,也為了以后能直接甩別人一臉文章,所以開始挖這樣一個大坑:簡單易懂的ECMA規范導讀。
希望能以專題的形式有線索地基于ECMA標準介紹Javascript的方方面面。本文不是ECMA標準的中文翻譯,也不是Javascript的入門教程,
本文雖然以JS的常見問題切入,但并不適合想要快速了解這些問題的人(Google才是快速了解問題的正解)。
本文的聚焦于標準如何決定了JS的各種行為,JS引擎的水面下在發生些什么。
本文描述的是ECMA262的5.1版本 也是現在最為流行和主流的標準,
現代瀏覽器和NodeJS默認均遵循此標準。盡量以英文原版為基礎,為了流暢,可能會使用某些名詞的中文翻譯,
但會將匹配的英文名詞以此種樣式中出現一次以避免誤解。
我們的第一個話題是:this指向哪里?
什么是this11.1.1 The this Keyword
The this keyword evaluates to the value of the ThisBinding of the current execution context.
計算this關鍵字時,取當前執行上下文的ThisBinding的值
10.3 Execution Contexts
執行上下文Execution Context 從邏輯上形成棧結構,棧頂(活躍)的執行上下文包含了追蹤當前正在執行的代碼的全部狀態。
執行上下文包含了LexicalEnvironment、VariableEnvironment和ThisBinding三部分,在這個話題中我們主要關心ThisBinding,
也就是代碼中出現this所代指的值的綁定
從最簡單的開始
10.4.1 Entering Global Code
在進入全局代碼的流程中,規范明確指出:全局代碼對應的執行上下文中,
Set the ThisBinding to the global object.
所以全局代碼中,this指向全局對象
函數調用表達式時提供的this值注意:this值this value是不同于this關鍵詞的概念,是調用[[Call]]內部方法的參數之一,并不等同于用戶代碼中的this關鍵字
函數調用表達式CallExpression的過程中,按照標準的描述,
計算this值的偽代碼如下
if Type(ref) isif IsPropertyReference(ref) thisValue := getBase(ref) else # assert Type(getBase(ref)) is thisValue := getBase(ref).ImplicitThisValue() else thisValue := undefined
ref是函數調用參數左側(括號左側)的表達式計算的結果
標示符引用Identifier Reference
即變量引用,引用base是環境記錄Environment Record
字面量引用Literal Reference
引用base也是環境記錄
屬性訪問Property Accessors
包括點運算和[]運算,引用base是左值
非引用類型常見的有
全部ECMA內置函數和所有用戶定義函數的返回結果(例外是host objects,也就是假設DOM之類的宿主對象如果需要,
可以定義一些函數返回引用)
環境記錄是前述的執行上下文中的LexicalEnvironment和VariableEnvironment的構成要素
不考慮with語句的話,環境記錄只有Declarative Environment Records一種,它的ImplicitThisValue始終返回undefined
綜上所述,排除with語句的情況下,想讓thisValue不是undefined,就只有屬性訪問一種辦法而已。
計算得到thisValue后,調用被調函數func的[[call]]內部方法,提供thisValue作為this的值
new表達式時提供的this值new表達式NewExpression的執行過程
基本上委托給了[[Construct]]內部方法,我們看這個方法的定義,
關注其中第8步
Let result be the result of calling the [[Call]] internal property of F, providing
obj as the this value and providing the argument list passed into [[Construct]] as args.
其中F是構造函數,而obj是本次新建的對象,非常清楚。
this值如何轉變為ThisBinding前兩節我們描述了兩種觸發函數體內代碼的辦法各自如何構造this值,但正如前述,this關鍵字的值是執行上下文中的ThisBinding決定的,
this值轉變為ThisBinding的過程發生在調用[[Call]]內部方法時,我們看標準
Let funcCtx be the result of establishing a new execution context for function
code using the value of F"s [[FormalParameters]] internal property, the passed
arguments List args, and the this value as described in 10.4.3.
阿哈,第一步就是建立新的執行上下文,其中thisBinding的構建在10.4.3 Entering Function Code
中描述,
if function-code isThisBinding = thisArg else if thisArg is null or thisArg is undefined ThisBinding = global object else if Type(thisArg) is not
這就是魔術的秘密
null 和 undefined 的this在此時會綁定為全局對象
其他三種非對象 String / Boolean / Number 在此時被轉化為對象(auto boxing)
但是,strict mode下不進行任何轉換
That"s this in Javascript.
本節思考題:
找找看關于apply和call的標準,為何this會變?
找找看關于bind的標準,哪里體現了bind后的函數內的this無視環境和調用方式,總是固定值?
with語句并不是一個良好的實踐,所以我避開了它,不過這可以作為閱讀標準的練習:with語句如何影響this關鍵詞?請試著寫一句代碼展示此種影響
eval的內部的this如何確定?
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78089.html
摘要:關于在絕大多數情況下,函數的調用方式決定了的值。不能在執行期間被賦值,并且在每次函數被調用時的值也可能會不同。它們除了參數略有不同,其功能完全一樣。它們的第一個參數都為將要指向的對象。 關于 this 在絕大多數情況下,函數的調用方式決定了this的值。this不能在執行期間被賦值,并且在每次函數被調用時this的值也可能會不同。 全局 this window.something = ...
摘要:一個表示編譯器檢測到一個無效的引用值。在實際情況中,往往是在獲取一個未被賦值的引用時被拋出。任何一個函數上下文都有一個被稱為活動對象的變量對象。沒有找到的話,就會認為引用名沒有基礎值并拋出的錯誤。下沒有下的屬性僅存在于被啟動的情況下。 和其他語言相比,javascript中的對于undefined的理解還是有點讓人困惑的。特別是試著理解ReferenceErrors錯誤(x is no...
摘要:標準對象,語義由本規范定義的對象。三個冒號作為分隔符分割數字字符串文法的產生式。所有因為帶來的問題,基本上是占著茅坑不拉屎的行為導致。以數組測試操作為例,標準中的描述如下相對于來說,規范中增加了對的處理。 前言 本文是對《ECMAScript 2018 Language Specification》的解讀。本文是對標準的概述性導讀,不是對 ES2018特性的詳細描述,也不會針對某個技術...
摘要:一規范中二規范中三規范中四分析過程分析五證明流程 Why in JavaScript both Object instanceof Function and Function instanceof Object return true? 一、ECMA5.1規范中instanceof /* how instanceof is defined by ECMA 5.1 Specificati...
閱讀 1933·2023-04-26 01:56
閱讀 3116·2021-11-18 10:02
閱讀 3061·2021-09-09 11:35
閱讀 1300·2021-09-03 10:28
閱讀 3421·2019-08-29 18:36
閱讀 2852·2019-08-29 17:14
閱讀 837·2019-08-29 16:10
閱讀 1620·2019-08-26 13:45