簡體   English   中英

JavaScript 的詞法環境如何維護嵌套塊范圍內的變量聲明?

[英]How does JavaScript's lexical environment maintain variables declarations within nested block scopes?

我已經閱讀了幾篇關於執行上下文的更全面的文章,現在我有點困惑和頭腦混亂。

為了使問題盡可能簡短,避免長時間引用,我最好嘗試通過一個專注於我無法獲得的細節的示例來說明我的心理模型,以便您可以糾正我並指出錯誤。

下面是一個例子:

var tomato = 'global tomato';

{
  let tomato = 'block tomato';
  console.log(tomato); // 'block tomato'
}

console.log(tomato); // 'global tomato'

到目前為止,一切都清楚了。 當 JS 引擎創建一個執行上下文(在我們的例子中是全局的)時,第一行的var tomato聲明被放置到一個Variable Environmentlet tomato塊范圍內的let tomato進入一個Lexical Environment 這解釋了我們如何最終得到 2 個不同的西紅柿。

現在,讓我們添加另一個番茄,如下所示:

var tomato = 'global tomato';

{
  let tomato = 'block tomato';

  {
    console.log(tomato); // ReferenceError: Cannot access 'tomato' before initialization
    let tomato = 'nested block tomato';
  }

  console.log(tomato); // won't reach here
}

console.log(tomato); // won't reach here

ReferenceError不足為奇。 事實上,我們試圖在變量被初始化之前訪問它,這被稱為臨時死區。 這很好地表明 JS 已經在最嵌套的塊中創建了另一個變量tomato 在我們引用它的那一刻,JS 也已經意識到這個tomato未被初始化。 否則,它會從外部作用域中抓取tomato ,這等於'block tomato'而不會拋出任何錯誤。 因此,讓我們修復錯誤並交換行,如下所示:

var tomato = 'global tomato';

{
  let tomato = 'block tomato';

  {
    let tomato = 'nested block tomato';
    console.log(tomato); // 'nested block tomato'
  }

  console.log(tomato); // 'block tomato' - still 'block tomato'. Nothing has been overwritten.
}

console.log(tomato); // 'global tomato'

我想知道 JavaScript 如何管理這個嵌套最多的塊。 因為到執行到達該行時:

let tomato = 'nested block tomato';

執行上下文的Lexical Environment已經包含在外部作用域中用'block tomato'值初始化的變量tomato 假設 JS 不只為代碼塊創建一個新的執行上下文(分別使用詞法和變量環境)(這只是函數調用和全局腳本的情況,對吧?)並且顯然,它不會覆蓋現有的變量具有相同名稱但來自嵌套塊作用域的Lexical Environment 正如最后一段代碼所示,其中創建了一個全新的獨立變量來保存值'nested block tomato'

那么問題來了,這個變量究竟存儲在哪里呢? 我的意思是執行上下文只有一個Lexical Environment ,但我們可能會創建許多嵌套的作用域來聲明變量。 我正在努力想象這些變量的存儲位置以及整個事情如何組合在一起。

假設 JS 不只為代碼塊創建一個新的執行上下文(分別使用詞法和變量環境)(這只是函數調用和全局腳本的情況,對吧?)

這是一個錯誤的假設。

規格

詞法環境是一種規范類型,用於根據 ECMAScript 代碼的詞法嵌套結構定義標識符與特定變量和函數的關聯。 詞法環境由環境記錄和對外部詞法環境的可能為空的引用組成。 通常,詞法環境與 ECMAScript 代碼的某些特定句法結構相關聯,例如 FunctionDeclaration、BlockStatement 或 TryStatement 的 Catch 子句,並且每次評估此類代碼時都會創建一個新的詞法環境。

塊語句創建了一個新的詞法環境。

在 ECMAScript 中,詞法作用域可以嵌套。

我的意思是執行上下文只有一個詞法環境,但我們可能會創建許多嵌套的作用域來聲明變量。

不,有一個詞法環境用於……嗯……每個詞法環境。 (畢竟,“范圍”只是“環境”的不同術語。)

規范不強制實現者以任何特定方式實現這一點。 一種典型的方法可能是擁有環境的鏈接列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM