Ale*_*lex 4 javascript variables ecmascript-6
鉴于这个例子:
var number = 10
{
var number = 42
}
console.log(number) // 42
Run Code Online (Sandbox Code Playgroud)
为什么第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
Run Code Online (Sandbox Code Playgroud)
但没有let:
let number = 10
let number = 42 // SyntaxError
console.log(number)
Run Code Online (Sandbox Code Playgroud)
为什么var给予"免费通行证"?是否与使用number时重新分配给窗口对象的属性有关var?
您可以var在JavaScript中重新声明变量,即使在严格模式下也是如此.
声明的变量的范围
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);Run Code Online (Sandbox Code Playgroud)
Uncaught SyntaxError: Identifier 'number' has already been declared?正如Sébastien已经提到的,声明的变量var在当前执行上下文中声明,并且可以重新声明.可以将执行上下文的概念与框进行比较.根据ECMAScript语言规范第8.3节:
8.3执行上下文
一个执行上下文是用于由ECMAScript实现跟踪代码的运行时计算的规范装置.在任何时间点,每个代理程序最多只有一个执行上下文实际执行代码.这称为代理程序的运行执行上下文.
[...]
ECMAScript代码的执行上下文具有表22中列出的其他状态组件.
表22:ECMAScript代码执行上下文的附加状态组件Component Purpose
LexicalEnvironment Identifies the Lexical Environment used to resolve identifier references made by code within this execution context. VariableEnvironment Identifies the Lexical Environment whose EnvironmentRecord holds bindings created by VariableStatements within this execution context.
因此,每次编写JavaScript代码时,它都被分成几个小的"盒子",称为执行上下文,只要解释器遇到一个新的语法结构(如块,函数声明等)就会创建.在每个框中,都有许多组件,但特别是LexicalEnvironment和VariableEnvironment.这些都是父执行上下文"框"内的"迷你框",它们保存对代码可以访问的当前执行上下文中声明的变量的引用.LexicalEnvironment是指用let和声明的变量const.VariableEnvironment指用变量创建的变量var.
现在看第13.3.2节:
13.3.2变量声明
注意var语句声明了作用于正在运行的执行上下文的VariableEnvironment的变量.Var变量在实例化包含词法环境时创建,并在创建时初始化为undefined.在任何VariableEnvironment的范围内,常见的BindingIdentifier可能出现在多个VariableDeclaration中,但这些声明共同只定义一个变量.
引用说明的最后一部分说明了您可以var多次声明的原因.每次解释器遇到一个函数时,VariableEnvironment都会创建一个new ,因为它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
Run Code Online (Sandbox Code Playgroud)
正如你所说,let并且const是块范围的.它们不会抛出错误,因为{ … }会创建一个新块.
var给予"免费通行证"?是否与使用number时重新分配给窗口对象的属性有关var?如前所述,声明var可以在a内多次发生VariableEnvironment- 但同样的情况并不适用于let和const.正如Bergi所提到的那样,ECMAScript的作者var直到很久以后才意识到有这么糟糕的声明者的垮台和怪癖,改变var行为会导致整个互联网崩溃,因为向后兼容性是ECMAScript/JavaScript的一个重要方面. .因此,作者引入了新的说明符,let并const会的目标是块范围的和可预测的,更喜欢你在其他语言看其他说明符.因此,只要在同一范围内有另一个声明let,const声明就会抛出错误.这与此无关window,仅仅是因为兼容性和历史问题.
| 归档时间: |
|
| 查看次数: |
672 次 |
| 最近记录: |