js做用域,js做用域鏈

對於這個我用蹩腳的英語翻譯了一篇英文文章,便於之後查閱,原本這文章是有中文版的可是如今連接跳不過去QAQ。express

原文連接:http://dmitrysoshnikov.com/ecmascript/chapter-4-scope-chain/數組

這篇文章不要求所有看懂,好比with不必去糾結,由於如今with和eval是不推薦使用的,可是看完這篇文章應該要對做用域和做用域鏈有個概念,這將會幫助理解js的this這些。閉包

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

一、Introduction 簡介less

二、Definition 定義ecmascript

  2.1 Function life cycle 函數生命週期ide

    2.1.1 Function creation 函數的建立函數

    2.1.2 Function activation 函數的激活ui

   2.2 Scope features 做用域的面紗this

    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  代碼執行過程當中對做用域鏈的影響

 

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.

本章將詳細介紹與執行環境直接相關的內容;此次,咱們將提到做用域鏈的主題。

二、定義

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.一、函數生命週期

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

函數的生命週期分爲,建立階段、激活階段(運行)。讓咱們自仔細考慮一下。

2.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.二、函數激活

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 xy 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.二、做用域特徵

Let’s consider some important features related with Scope chain and [[Scope]]property of functions.

讓咱們來考慮函數一些重要的特徵,做用域鏈做用域屬性

2.2.一、閉包

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.二、經過構造函數的函數建立的[[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 Functionconstructor 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.三、二維做用域鏈查找

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.四、全局做用域鏈和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.五、代碼執行過程當中對做用域鏈的影響

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未執行的時候

三、結論

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]]屬性直接相關,閉包它在其餘的章節中討論。我很高興在評論中回答你的問題。

相關文章
相關標籤/搜索