天天看點

js作用域,js作用域鍊

對于這個我用蹩腳的英語翻譯了一篇英文文章,便于以後查閱,本來這文章是有中文版的但是現在連結跳不過去QAQ。

原文連結:http://dmitrysoshnikov.com/ecmascript/chapter-4-scope-chain/

這篇文章不要求全部看懂,比如with沒必要去糾結,因為現在with和eval是不推薦使用的,但是看完這篇文章應該要對作用域和作用域鍊有個概念,這将會幫助了解js的this這些。

本人英語水準垃圾和知識水準有限 ,文章是根據我的了解來翻譯的,如果有翻譯不恰當的地方,請務必在評論中糾正,謝謝♪(・ω・)ノ。

1、Introduction 簡介

2、Definition 定義

  2.1 Function life cycle 函數生命周期

    2.1.1 Function creation 函數的建立

    2.1.2 Function activation 函數的激活

   2.2 Scope features 作用域的面紗

    2.2.1 Closures 閉包 

    2.2.2 [[Scope]] of functions created via Function constructor  通過構造函數的函數建立的[[Scope]]

    2.2.3 Two-dimensional Scope chain lookup  二維作用域鍊查找

    2.2.4 Scope chain of the global and eval contexts 全局作用域鍊和eval執行環境

    2.2.5 Affecting on Scope chain during code execution  代碼執行過程中對作用域鍊的影響

  • 3、Conclusion 總結

1、Introduction

1、簡介

As we already know from the second chapter concerning the variable object, the data of an execution context (variables, function declarations, and formal parameters of functions) are stored as properties of the variables object.

正如我們已經從第二章關于變量對象所知道的,執行環境的資料(變量、函數聲明和函數的形式參數)被存儲為變量對象的屬性。

Also, we know that the variable object is created and filled with initial values every time on entering the context, and that its updating occurs at code execution phase.

而且,我們知道可變對象在每次進入執行環境時被建立并初始化,并且它的更新發生在代碼執行階段。

This chapter is devoted one more detail directly related with execution contexts; this time, we will mention a topic of a scope chain.

本章将詳細介紹與執行環境直接相關的内容;這次,我們将提到作用域鍊的主題。

2、Definition

2、定義

If to describe briefly and showing the main point, a scope chain is mostly related with inner functions.

如果要簡要描述和顯示要點,作用域鍊多與function有關。

As we know, ECMAScript allows creation of inner functions and we can even return these functions from parent functions.

正如我們所知,ECMAScript允許建立内部函數,甚至可以從父函數傳回這些函數。

var x = 10;
function foo() { 
  var y = 20;
  function bar() {
    alert(x + y);
  }
  return bar;
}
foo()(); // 30      

Thus, is known that every context has its own variables object: for the global context it is global object itself, for functions it is the activation object.

是以,我們知道每個執行環境都擁有變量對象。對于全局他的變量對象就是它自己,對于函數來說,它是個活躍對象。

And the scope chain is exactly this list of all (parent) variable objects for the inner contexts. This chain is used for variables lookup. I.e. in the example above, scope chain of “bar” context includes AO(bar), AO(foo) and VO(global).

作用域鍊正好是該函數執行環境的所有(父)變量對象的清單。這個作用域鍊用于變量查找。也就是說,在上面的例子中,“bar”上下文的範圍鍊包括AO(bar)、AO(Foo)和VO(全局)。

But, let’s examine this topic in detail.

但是,讓我們詳細研究這個話題。

Let’s begin with the definition and further will discuss deeper on examples.

讓我們從定義開始,進一步讨論例子。

Scope chain is related with an execution context a chain of variable objects which is used for variables lookup at identifier resolution.

作用域鍊與執行環境相關聯的變量對象,用于變量的辨別符查找解析。

The scope chain of a function context is created at function call and consists of the activation object and the internal [[Scope]] property of this function. We will discuss the [[Scope]] property of a function in detail below.

函數作用域鍊在函數調用中建立,并由該函數的活躍對象和内部[[Scope]]屬性組成。下面我們将詳細讨論函數的[[Scope]]屬性。

Schematically in the context:

如上示意:

activeExecutionContext = {
    VO: {...}, // or AO  → VO就是variable object 變量對象   AO就是 activation Object 活躍對象
this: thisValue,
    Scope: [ // Scope chain 作用域鍊
      // list of all variable objects 所有變量對象清單
      // for identifiers(辨別符) lookup  用于辨別符查找
    ] 
};      

where Scope by definition is:

在那裡作用域的定義:

Scope = AO + [[Scope]]      

For our examples we can represent Scope, and [[Scope]] as normal ECMAScript arrays:

我們的例子中可以使用正常的js數組來代表作用域鍊:

var Scope = [VO1, VO2, ..., VOn]; // scope chain 作用域鍊      

The alternative structure view can be represented as a hierarchical object chain with the reference to the parent scope (to the parent variable object) on every link of the chain. For this view corresponds __parent__ concept of some implementations which we discussed in the second chapter devoted variable object:

另一個結構視圖可以表示為連結清單的每個鍊上的父對象範圍(父變量對象)的分層對象鍊。對于這一觀點,我們在第二章中讨論了一些變量對象:

var VO1 = {__parent__: null, ... other data}; -->
var VO2 = {__parent__: VO1, ... other data}; -->
// etc.      

But to represent a scope chain using an array is more convenient, so we will use this approach. Besides, the specification statements abstractly itself (see 10.1.4) that “a scope chain is a list of objects”, regardless that on the implementation level can be used the approach with the hierarchical chain involving the __parent__ feature. And the array abstract representation is a good candidate for the list concept.

但是,使用數組表示作用域鍊更友善,是以我們将使用這種方法。此外,規範聲明本身抽象(參見101.4),“作用域鍊是對象清單”,無論那種實作方式,都可以使用__parent__為特征的作用域鍊。數組表示抽象清單概念是一個很好的選擇。

The combination AO + [[Scope]] and also process of identifier resolution, which we will discuss below, are related with the life cycle of functions.

AO + [[Scope]] 的辨別符解析。我們将在下面函數的生命周期讨論。

2.1、Function life cycle

2.1、函數生命周期

Function life cycle is divided into a stage of creation and a stage of activation (call). Let’s consider them in detail.

函數的生命周期分為,建立階段、激活階段(運作)。讓我們自仔細考慮一下。

2.1.1、Function creation

2.1.1、函數的建立

As is known, function declarations are put into variable/activation object (VO/AO) on entering the context stage. Let’s see on the example a variable and a function declaration in the global context (where variable object is the global object itself, we remember, yes?):

我們都知道,執行環境階段,函數的聲明被放入變量對象或活躍對象中。讓我們在全局環境(全局環境的變量對象是全局對象本身,我們記得,是嗎?),看看這個例子的變量和函數聲明。

var x = 10;
  
function foo() {
  var y = 20;
  alert(x + y);
}
  
foo(); // 30      

At function activation, we see correct (and expected) result – 30. However, there is one very important feature.

運作函數後,我們看見 alert彈出的是30。然而這裡有個很重要的特征。

Before this moment we spoke only about variable object of the current context. Here we see that “y” variable is defined in function “foo” (which means it is in the AO of “foo” context), but variable “x” is not defined in context of “foo” and accordingly is not added into the AO of “foo”. At first glance “x” variable does not exist at all for function “foo”; but as we will see below — only “at first glance”. We see that the activation object of “foo” context contains only one property — property “y”:

在此之前,我們隻讨論了執行環境的變量對象。這裡我們看到變量y在函數foo的定義(也就是y在foo的執行環境的活躍對象【AO】裡)。但是變量x不在foo中定義,是以x不會被添加到函數foo的活躍對象AO裡。乍一看,變量x不存在于函數foo。但是正如我們看到的,就是"乍一看"。我們看到foo的執行環境的活躍對象AO隻包含了一個屬性y:

fooContext.AO = {
  y: undefined // undefined – on entering the context, 20 – at activation
};      

How does function “foo” have access to “x” variable? It is logical to assume that function should have access to the variable object of a higher context. In effect, it is exactly so and, physically this mechanism is implemented via the internal [[Scope]] property of a function.

函數“foo”如何通路“x”變量?假定函數應該通路較高執行環境的變量對象是複合邏輯的。實際上,它是這樣的,在實體上,這個機制是通過函數的[[Scope]]屬性來實作的。

[[Scope]] is a hierarchical chain of all parent variable objects, which are above the current function context; the chain is saved to the function at its creation.

在目前函數執行環境[[Scope]]是父對象的鍊,鍊在被建立的時候儲存到函數中.

Notice the important point — [[Scope]] is saved at function creation — statically (invariably), once and forever — until function destruction. I.e. function can be never called, but [[Scope]] property is already written and stored in function object.

注意重要的一點,[[Scope]]在函數建立時永遠靜止不變地被儲存,直到函數銷毀。I.e. 函數不被調用,但是[[Scope]]屬性已經寫好存儲在函數對象中。

Another moment which should be considered is that [[Scope]] in contrast with Scope (Scope chain) is the property of a function instead of a context. Considering the above example, [[Scope]] of the “foo” function is the following:

此時值得考慮的是作用域[[Scope]]和作用域鍊的對比而不是執行環境的對比。就上述而論,foo的[[Scope]]如下:

foo.[[Scope]] = [
  globalContext.VO // === Global  ===全局
];      

And further, by a function call as we know, there is an entering a function context where the activation object is created and this value and Scope (Scope chain) are determined. Let us consider this moment in detail.

此外,通過我們知道的函數調用。函數執行環境建立其活躍對象建立它的值,确定作用域鍊。讓我們詳細地考慮一下這個時候。

2.1.2、Function activation

2.1.2、函數激活

As it has been said in definition, on entering the context and after creation of AO/VO, Scope property of the context (which is a scope chain for variables lookup) is defined as follows:

正如在定義中所說的,推入執行環境和建立AO或者是VO,作用域的屬性在執行環境中(它是變量查找的作用域鍊),定義如下:

Scope = AO|VO + [[Scope]]      

High light here is that the activation object is the first element of the Scope array, i.e. added to the front of scope chain:

這裡的高亮是活躍對象(//也就是說的[AO])在作用域數組的第一個元素。i.e.添加到作用域鍊的前面:

Scope = [AO].concat([[Scope]]);      

 This feature is very important for the process of identifier resolution.

這個特性對于辨別符的解析過程非常重要。

Identifier resolution is a process of determination to which variable object in scope chain the variable (or the function declaration) belongs.

辨別符的解析是一個确定的過程,在作用域鍊中的變量屬于它的活躍對象。

On return from this algorithm we have always a value of type Reference, which base component is the corresponding variable object (or null if variable is not found), and a property name component is the name of the looked up (resolved) identifier. In detail Reference type is discussed in the Chapter 3. This.

從該計算程式傳回,我們總是有一個引用類型的值,它指向變量對象(如果找不到變量指向null)。屬性名是查找到(已解析)辨別符的名稱組成。 Chapter 3. This詳細讨論了引用類型。

Process of identifier resolution includes lookup of the property corresponding to the name of the variable, i.e. there is a consecutive examination of variable objects in the scope chain, starting from the deepest context and up to the top of the scope chain.

辨別符解析過程包括查找與變量名對應的屬性。i.e.在作用域鍊對變量對象進行連續檢查。從最下面的作用域開始,直到作用域鍊的頂部。

Thus, local variables of a context at lookup have higher priority than variables from parent contexts, and in case of two variables with the same name but from different contexts, the first is found the variable of deeper context.

是以,查找時執行環境的局部變量比來自父執行環境的變量具有更高的優先級,萬一有兩個變量同名的情況但在不同執行環境,查找的第一個是在最裡面的執行變量。

Let’s a little complicate an example described above and add additional inner level:

如上所述讓我們把一個例子複雜化,在函數裡面在添加一個:

var x = 10;
  
function foo() {
  
  var y = 20;
  
  function bar() {
    var z = 30;
    alert(x +  y + z);
  }
  
  bar();
}
  
foo(); // 60      

For which we have the following variable/activation objects, [[Scope]] properties of functions and scope chains of contexts:

為此,我們有變量對象/活躍對象。函數有[[Scope]]屬性,執行環境有作用域鍊:

Variable object of the global context is:

變量對象在全局執行環境:

globalContext.VO === Global = {
  x: 10
  foo: <reference to function>
};      

At 

foo

 creation, the 

[[Scope]]

 property of 

foo

 is:

在foo的建立,foo的[[Scope]]屬性:

foo.[[Scope]] = [
  globalContext.VO
];      

At 

foo

 function call, the activation object of 

foo

 context is:

在foo函數的執行,foo執行環境的活躍對象:

fooContext.AO = {
  y: 20,
  bar: <reference to function>
};      

And the scope chain of 

foo

 context is:

foo執行環境中的作用域鍊:

fooContext.Scope = fooContext.AO + foo.[[Scope]] // i.e.:
 
fooContext.Scope = [
  fooContext.AO,
  globalContext.VO
];      

At creation of inner 

bar

 function its 

[[Scope]]

 is:

建立的内部bar函數它的[[Scope]]:

bar.[[Scope]] = [
  fooContext.AO,
  globalContext.VO
];      

At 

bar

 function call, the activation object of 

bar

 context is:

執行bar函數,它的執行環境的活躍對象:

barContext.AO = {
  z: 30
};      

And the scope chain of 

bar

 context is:

bar執行環境中的作用域鍊:

barContext.Scope = barContext.AO + bar.[[Scope]] // i.e.:
 
barContext.Scope = [
  barContext.AO,
  fooContext.AO,
  globalContext.VO
];      

Identifier resolution for 

x

y

 and 

z

 names:

辨別符解析的名字:

- "x"
-- barContext.AO // not found
-- fooContext.AO // not found
-- globalContext.VO // found - 10

- "y"
-- barContext.AO // not found
-- fooContext.AO // found - 20

- "z"
-- barContext.AO // found - 30      

2.2、Scope features

2.2、作用域特征

Let’s consider some important features related with Scope chain and 

[[Scope]]

property of functions.

讓我們來考慮函數一些重要的特征,作用域鍊作用域屬性

2.2.1、Closures

2.2.1、閉包

Closures in ECMAScript are directly related with the 

[[Scope]]

 property of functions. As it has been noted, 

[[Scope]]

 is saved at function creation and exists until the function object is destroyed. Actually, a closure is exactly a combination of a function code and its 

[[Scope]]

 property. Thus, 

[[Scope]]

 contains that lexical environment (the parent variable object) in which function is created. Variables from higher contexts at the further function activation will be searched in this lexical (statically saved at creation) chain of variable objects.

閉包在ECMAScript中與函數[[Scope]]屬性有關,正如我們注意到的,[[Scope]]在函數建立時被儲存,直到函數對象被銷毀。事實上,閉包恰好是函數代碼與其[[Scope]]屬性的組合,在這個函數中建立時[[Scope]]包含了詞法環境(函數的父級活躍對象)、變量都來自于上級執行環境,在進一步的函數活躍中,将會在這個(靜态儲存在建立)詞法鍊的活躍對象中搜尋

Examples:

var x = 10;
 
function foo() {
  alert(x);
}
 
(function () {
  var x = 20;
  foo(); // 10, but not 20
})();      

We see that 

x

 variable is found in the 

[[Scope]]

 of 

foo

 function, i.e. for variables lookup the lexical (closured) chain defined at the moment of function creation, but not the dynamic chain of the call (at which value of 

x

 variable would be resolved to 

20

) is used.

我們看看 在函數foo的[[Scope]]這個變量x ,i.e 在函數建立的時候,在定義的詞法(閉包)鍊中的變量查找,但是不是動态的去調用作用域鍊

Another (classical) example of closure:

另一個(經典)閉包執行個體:

function foo() {
 
  var x = 10;
  var y = 20;
 
  return function () {
    alert([x, y]);
  };
 
}
 
var x = 30;
 
var bar = foo(); // anonymous(匿名) function is returned
 
bar(); // [10, 20]      

Again we see that for the identifier resolution the lexical scope chain defined at function creation is used — the variable 

x

 is resolved to 

10

, but not to 

30

. Moreover, this example clearly shows that 

[[Scope]]

 of a function (in this case of the anonymous function returned from function 

foo

) continues to exist even after the context in which a function is created is already finished.

我們在次看到 使用在函數建立中定義的詞法範圍鍊的辨別符來解析----這個變量x被解析為10,而不是30。此外,這個例子清楚的顯示 [[Scope]]在函數(在這種情況下,從函數foo傳回匿名函數)存在,甚至在建立函數的執行環境完成之後仍然存在。 

In more details about the theory of closures and their implementation in ECMAScript read in the Chapter 6. Closures.

關于閉包理論的更多細節和它們在ECMAScript中的實作,閱讀Chapter 6. Closures。

2.2.2、[[Scope]] of functions created via Function constructor

2.2.2、通過構造函數的函數建立的[[Scope]]

In the examples above we see that function at creation gets the 

[[Scope]]

 property and via this property it accesses variables of all parent contexts. However, in this rule there is one important exception, and it concerns functions created via the Function constructor.

在上面的例子中,我們看到函數建立 擷取[[Scope]]屬性,通過這個屬性通路所有父級執行環境的變量。然而,在這個規則裡這是個重要的例外,它涉及通過構造函數建立的函數。

var x = 10;
  
function foo() {
  
  var y = 20;
  
  function barFD() { // FunctionDeclaration  函數聲明
    alert(x);
    alert(y);
  }
  
  var barFE = function () { // FunctionExpression 函數表達式
    alert(x);
    alert(y);
  };
  
  var barFn = Function('alert(x); alert(y);'); /*因為Function是來自于全局的是以他不能通路函數foo裡的變量。除非把y改為全局的*/
  
  barFD(); // 10, 20
  barFE(); // 10, 20
  barFn(); // 10, "y" is not defined       
}
  
foo();      

As we see, for 

barFn

 function which is created via the 

Function

 constructor the variable 

y

 is not accessible. But it does not mean that function 

barFn

 has no internal 

[[Scope]]

 property (else it would not have access to the variable 

x

). And the matter is that 

[[Scope]]

 property of functions created via the 

Function

constructor contains always only the global object. Consider it since, for example, to create closure of upper contexts, except global, via such function is not possible.

我們看到,對于barFn函數,通過Function構造 變量y無法通路。但是這并不意味着 函數barFn内部沒有[[Scope]]屬性(否則他不會 通路到變量x)。問題是[[Scope]]屬性,通過Function構造在函數建立,總是隻包含全局對象。自認為例如,上層執行環境建立閉包,除了全局,這樣使用函數是不合理的。

2.2.3、Two-dimensional Scope chain lookup

2.2.3、二維作用域鍊查找

Also, an important point at lookup in scope chain is that prototypes (if they are) of variable objects can be also considered — because of prototypical nature of ECMAScript: if property is not found directly in the object, its lookup proceeds in the prototype chain. I.e. some kind of 2D-lookup of the chain: (1) on scope chain links, (2) and on every of scope chain link — deep into on prototype chain links. We can observe this effect if define property in 

Object.prototype

:

而且,重點查找作用域鍊的原型(如果他們是的話) 變量對象也可以考慮。----由于原型的性質在ECMAScript:如果直接在對象裡未找到屬性,就在原型鍊中查找。I.e 某種在鍊中的二維查找:(1)作用域鍊的連結 (2)以及在作用域鍊上的每一個環節----關于原型鍊的深入探讨。如果在Object.prototype中定義屬性,我們可以觀察到這種效果:

function foo() {
  alert(x);
}
  
Object.prototype.x = 10;
  
foo(); // 10      

Activation objects do not have prototypes what we can see in the following example:

活躍對象沒有原型,在下面的例子我們可以看到:

function foo() {
  
  var x = 20;
  
  function bar() {
    alert(x);
  }
  
  bar();
}
  
Object.prototype.x = 10;
  
foo(); // 20      

If activation object of 

bar

 function context would have a prototype, then property 

x

 should be resolved in 

Object.prototype

 because it is not resolved directly in AO. But in the first example above, traversing the scope chain in identifier resolution, we reach the global object which (in some implementation but not in all) is inherited from 

Object.prototype

 and, accordingly, 

x

 is resolved to 

10

.

如果bar函數執行環境的活躍對象有原型,然後原型x應該為對象Object.prototype,因為它不能直接在AO裡确定。但是在上面第一個例子中(//這裡說的是上面代碼的再上面的代碼),我們辨別符解析周遊原型鍊,直到周遊到全局對象(在某些實作中,但不是全部)。它繼承Object.prototype,是以x的值為10。

The similar situation can be observed in some versions of SpiderMokey with named function expressions (abbreviated form is NFE), where special object which stores the optional name of function-expression is inherited from 

Object.prototype

, and also in some versions of Blackberry implementation where activation objects are inherited from Object.prototype. But more detailed this features are discussed in Chapter 5. Functions.

可以觀察到類似的情況,SpiderMokey的一些版本 命名函數表達式(縮寫形式是NFE)。其中存儲函數表達式任意名稱的特殊對象是繼承Object.propotype的,另外一些版本的 關于Blackberry的實作,在那裡的活躍對象繼承Object.propotype。在Chapter 5. Functions 讨論了更詳細的特征。

2.2.4、Scope chain of the global and eval contexts

2.2.4、全局作用域鍊和eval執行環境

Here is not so much interesting, but it is necessary to note. The scope chain of the global context contains only global object. The context with code type “eval” has the same scope chain as a calling context.

這裡沒有那麼有趣,但有必要注意。全局執行環境的作用域鍊隻有一個全局對象。執行環境裡'eval'代碼類型有一樣作用域鍊,作為執行的執行環境

globalContext.Scope = [
  Global
];
  
evalContext.Scope === callingContext.Scope;      

2.2.5、Affecting on Scope chain during code execution

2.2.5、代碼執行過程中對作用域鍊的影響

In ECMAScript there are two statements which can modify scope chain at runtime code execution phase. These are with statement and catch clause. Both of them add to the front of scope chain the object required for lookup identifiers appearing within these statements. I.e., if one of these case takes place, scope chain is schematically modified as follows:

在ECMAScript 在代碼執行階段有兩個語句可以修改作用域鍊,是with語句和catch捕獲。它們都添加到範圍鍊的前面,用于查找這些語句中出現的辨別符所需的對象。I.e  如果這兩個其中一個的代碼執行了,伴随着作用域鍊的修改:

Scope = withObject|catchObject + AO|VO + [[Scope]]      

The statement with in this case adds the object which is its parameter (and thus properties of this object become accessible without prefix):

這種情況下這個語句添加了對象是其參數。(是以該對象的屬性變成了,沒有字首來通路)

var foo = {x: 10, y: 20};
  
with (foo) {
  alert(x); // 10
  alert(y); // 20
}      

Scope chain modification:

作用域鍊修改:

Scope = foo + AO|VO + [[Scope]]      

Let us show once again that the identifier is resolved in the object added by the with statement to the front of scope chain:

讓我們再次展示 ,對範圍鍊前面的with語句的對象中添加解析辨別符:

var x = 10, y = 10;
  
with ({x: 20}) {
  
  var x = 30, y = 30;
  
  alert(x); // 30
  alert(y); // 30
}
  
alert(x); // 10
alert(y); // 30      

What happened here? On entering the context phase, “x” and “y” identifiers have been added into the variable object. Further, already at runtime code executions stage, following modifications have been made:

  • x = 10, y = 10;
  • the object {x: 20} is added to the front of scope chain;
  • the met var statement inside with, of course, created nothing, because all variables have been parsed and added on entering the context stage;
  • there is only modification of “x” value, and exactly that “x” which is resolved now in the object added to the front of scope chain at second step; value of this “x” was 20, and became 30;
  • also there is modification of “y” which is resolved in variable object above; accordingly, was 10, became 30;
  • further, after with statement is finished, its special objects is removed from the scope chain (and the changed value “x” – 30 is removed also with that object), i.e. scope chain structure is restored to the previous state which was before with statement augmentation;
  • as we see in last two alerts: the value of “x” in current variable object remains the same and the value of “y” is equal now to 30 and has been changed at with statement work.

這裡發生了什麼?進入執行階段,'x'和'y'辨別符已經添加到變量對象中。進一步,已經是代碼執行階段了,經過修改:

  • x = 10, y = 10;
  • 對象{x: 20}添加到目前作用域鍊前面
  • 裡面的var語句,當然沒有建立任何東西。因為全部的變量已經解析過 添加在執行環境。
  • 這裡隻修改x的值,确切的說是修改x,現在在第二步解析了對象前面添加的作用域鍊。x由20變為了30。
  • 另外還有y的修改,它在上面的變量對象中被解析,是以由10變為了30。
  • 進一步,後面with語句結束,其特殊對象從作用域鍊中移除(并且改變的值“x”- 30也被移除。), i.e 作用域鍊結構恢複到with語句執行前的狀态。
  • 我們看到最後兩次alert:“x”在目前變量對象中的值保持不變。y在with語句執行後發生了變化,“y”現在是30。

Also, a 

catch

 clause in order to have access to the parameter-exception creates an intermediate scope object with the only property — exception parameter name, and places this object in front of the scope chain. Schematically it looks so:

另外,為了捕獲參數異常,catch在中間的作用域對象建立具有原型屬性--異常參數名稱,在将此對象放在作用域鍊前面。他看起來是這樣的:

try {
  ...
} catch (ex) {
  alert(ex);
}      

Scope chain modification:

作用域鍊修改:

var catchObject = {
  ex: <exception object>
};
  
Scope = catchObject + AO|VO + [[Scope]]      

After the work of catch clause is finished, scope chain is also restored to the previous state.

catch捕獲工作完成後,作用域鍊恢複到catch未執行的時候

3、Conclusion

3、結論

At this stage, we have considerate almost all general concepts concerning execution contexts and related with them details. Further, according to plan, — detailed analysis of function objects: types of functions (FunctionDeclaration, FunctionExpression) and closures. By the way, closures are directly related with the [[Scope]] property discussed in this article, but about it is in appropriate chapter. I will be glad to answer your questions in comments.

 現階段,我們考慮了幾乎所有關于執行環境的概念和與他們有關的細節。進一步,按計劃,----函數對象的詳細分析:函數類型(函數聲明FunctionDeclaration,函數表達式FunctionExpression)還有閉包。順便說閉包與本文讨論的[[Scope]]屬性直接相關,閉包它在其他的章節中讨論。我很高興在評論中回答你的問題。

轉載于:https://www.cnblogs.com/ruoyin/p/9034294.html

繼續閱讀