[英]Why let and const keyword variables are not allowed to redeclaration in JavaScript, where var keyword variable is allowed?
[英]Block-level variable redeclaration with var vs. let/const
鑒於這個例子:
var number = 10
{
var number = 42
}
console.log(number) // 42
為什么第4行沒有拋出Uncaught SyntaxError: Identifier 'number' has already been declared
? 由於塊作用域,它與let
/ const
一起使用(雖然輸出當然是10
而不是42
),但它如何與var
?
將此與以下相比較,它與var
:
var number = 10
var number = 42
console.log(number) // 42
但是不要let
:
let number = 10
let number = 42 // SyntaxError
console.log(number)
為什么var
被賦予“免費通行證”? 是否與使用var
時重新分配給窗口對象的number
屬性有關?
即使在嚴格模式下 ,您也可以在JavaScript中重新聲明var
變量。
用
var
聲明的變量的范圍是它的當前執行上下文 ,它是封閉函數,或者對於在任何函數外部聲明的變量,是全局的。 如果重新聲明JavaScript變量,它將不會丟失其值。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#var_hoisting
'use strict' var someVar = 'Hello'; var someVar = 2 + 2; console.log(someVar);
Uncaught SyntaxError: Identifier 'number' has already been declared
? 正如Sébastien已經提到的 ,用var
聲明的變量在當前執行上下文中聲明,並且可以重新聲明。 可以將執行上下文的概念與框進行比較。 根據ECMAScript語言規范第8.3節 :
8.3執行上下文
執行上下文是一種規范設備,用於跟蹤ECMAScript實現對代碼的運行時評估。 在任何時間點,每個代理程序最多只有一個執行上下文實際執行代碼。 這稱為代理程序的運行執行上下文 。
[...]
ECMAScript代碼的執行上下文具有表22中列出的其他狀態組件。
表22:ECMAScript代碼執行上下文的附加狀態組件\n 組件目的\n\n
\n\n LexicalEnvironment標識用於解析此執行上下文中的代碼所做的標識符引用的詞法環境。\n VariableEnvironment標識其EnvironmentRecord包含由此執行上下文中的VariableStatements創建的綁定的詞法環境。\n
因此,每次編寫JavaScript代碼時,它都被分成幾個小的“盒子”,稱為執行上下文,只要解釋器遇到一個新的語法結構(如塊,函數聲明等)就會創建。在每個框中,都有許多組件,但特別是LexicalEnvironment
和VariableEnvironment
。 這些都是父執行上下文“框”內的“迷你框”,它們保存對代碼可以訪問的當前執行上下文中聲明的變量的引用。 LexicalEnvironment
指的是用let
和const
聲明的變量。 VariableEnvironment
是指使用var
創建的變量。
現在看第13.3.2節 :
13.3.2變量聲明
注意var語句聲明了作用於正在運行的執行上下文的VariableEnvironment的變量。 Var變量在實例化包含詞法環境時創建,並在創建時初始化為undefined 。 在任何VariableEnvironment的范圍內,常見的BindingIdentifier可能出現在多個VariableDeclaration中,但這些聲明共同只定義一個變量。
引用注釋的最后一部分說明了為什么可以多次聲明var
的原因。 每次解釋器遇到一個函數時,都會創建一個新的VariableEnvironment
,因為var
是函數作用域的,如果你在全局作用域中,則有一個全局的VariableEnvironment
。 在您的情況下,您已在全局范圍內聲明了number
,因為{ … }
是一個塊,而不是一個函數,但它們共同只定義一number
。 因此,您的代碼實際執行與此相同:
var number = 10 //declared once
{
number = 42 //since { … } does not create a new VariableEnvironment, number is the same
//variable as the one outside the block. Thus, the two declarations only define
//number once and every redeclaraction is essentially reassignment.
}
console.log(number) //42
正如你所說, let
和const
是塊范圍的。 它們不會拋出錯誤,因為{ … }
會創建一個新塊。
var
被賦予“免費通行證”? 是否與使用var
時重新分配給窗口對象的number
屬性有關? 如前所述, var
可以在VariableEnvironment
多次出現 - 但對於let
和const
,同樣不會出現真正的問題。 作為BERGI提到 ,ECMAScript的作者沒有意識到的挫折和具有這樣的壞聲明符的怪癖var
直到很久以后,並改變var
的行為會導致整個網絡崩潰,因為向后兼容性是ECMAScript中的一個巨大的方面/ JavaScript的。 因此,作者引入了新的聲明符, let
和const
,其目標是塊作用域和可預測的,更像您在其他語言中看到的其他聲明符。 因此,只要在同一范圍內有另一個聲明, let
和const
聲明就會拋出錯誤。 這與window
無關,僅僅是因為兼容性和歷史問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.