Javascript 变量是用let还是const声明的?
我使用ES6已经有一段时间了,我注意到当使用Javascript 变量是用let还是const声明的?,javascript,ecmascript-6,constants,let,hoisting,Javascript,Ecmascript 6,Constants,Let,Hoisting,我使用ES6已经有一段时间了,我注意到当使用var声明的变量按照预期被提升时 console.log(typeof name); // undefined var name = "John"; …使用声明的变量let或const似乎在提升方面存在一些问题: console.log(typeof name); // ReferenceError let name = "John"; 及 这是否意味着使用let或const声明的变量不被提升?这到底是怎么回事?在这个问题上,let和const之间
var
声明的变量按照预期被提升时
console.log(typeof name); // undefined
var name = "John";
…使用声明的变量let
或const
似乎在提升方面存在一些问题:
console.log(typeof name); // ReferenceError
let name = "John";
及
这是否意味着使用let
或const
声明的变量不被提升?这到底是怎么回事?在这个问题上,let
和const
之间有什么区别吗?引用ECMAScript 6(ECMAScript 2015)规范的第节
变量是在实例化其包含词法的环境时创建的,但在对变量的词法绑定进行求值之前,可能无法以任何方式访问
因此,为了回答您的问题,是的,
让
和常量
提升,但在运行时评估实际声明之前,您无法访问它们。@thefourtheye正确地说,这些变量在声明之前无法访问。然而,它比这要复杂一点
使用let
或const
声明的变量是否未提升?这到底是怎么回事
所有声明(var
,let
,const
,函数
,函数*
,类
)在JavaScript中被“提升”。这意味着,如果在某个范围内声明了名称,则在该范围内,标识符将始终引用该特定变量:
x = "global";
// function scope:
(function() {
x; // not "global"
var/let/… x;
}());
// block scope (not for `var`s):
{
x; // not "global"
let/const/… x;
}
函数和块作用域1都是如此
var
/函数
/函数*
声明和let
/常量
/类
声明之间的区别在于初始化在作用域顶部创建绑定时,前者使用
未定义的或(生成器)函数进行初始化。但是,词汇声明的变量保持未初始化状态。这意味着当您尝试访问它时,会引发ReferenceError
异常。只有在对let
/const
/类
语句求值时,才会对其进行初始化,前面(上面)的所有内容都称为暂时死区
注意a让y
语句用未定义的初始化变量,如let y=undefined代码>会有
时间死区不是一个语法位置,而是变量(范围)创建和初始化之间的时间。在声明上方的代码中引用变量不是错误,只要该代码未执行(例如,函数体或简单的死代码),并且如果您在初始化之前访问变量,即使访问代码低于声明,也会引发异常(例如,在过早调用的已挂起功能声明中)
在这件事上,let
和const
之间有什么区别吗
不,就提升而言,它们的工作原理是相同的。它们之间唯一的区别是常量蚂蚁必须并且只能在声明的初始值设定部分分配(const one=1;
,两者都const one;
以及以后类似one=2
的重新分配无效)
1:var
声明仍然只在功能级别上起作用,当然ES6
引入了Let
变量,这些变量产生了块级别的作用域
。在ES5
之前,我们没有块级别的作用域
,因此在块内部声明的变量总是hoisted
到功能级别范围
基本上,Scope
指的是您的变量在程序中的可见位置,这决定了您可以在哪里使用您声明的变量。在ES5
中,我们有全局作用域、函数作用域和try/catch作用域
,在ES6
中,我们还可以使用Let获得块级作用域
- 当您使用
var
关键字定义变量时,从定义它的那一刻起就知道整个函数
- 当您使用
let
语句定义变量时,它只在所定义的块中已知
function doSomething(arr){
//i is known here but undefined
//j is not known here
console.log(i);
console.log(j);
for(var i=0; i<arr.length; i++){
//i is known here
}
//i is known here
//j is not known here
console.log(i);
console.log(j);
for(let j=0; j<arr.length; j++){
//j is known here
}
//i is known here
//j is not known here
console.log(i);
console.log(j);
}
doSomething(["Thalaivar", "Vinoth", "Kabali", "Dinesh"]);
第一个for
循环始终打印最后一个值,使用let
它创建一个新范围并绑定新值,打印我们1,2,3,4,5
谈到常量
,它的工作原理基本上类似于let
,唯一的区别是它们的值不能更改。在常量中允许变异,但不允许重新分配。
for(var i=1; i<6; i++){
setTimeout(function(){
console.log(i);
},1000)
}
for(let i=1; i<6; i++){
setTimeout(function(){
console.log(i);
},1000)
}
const foo = {};
foo.bar = 42;
console.log(foo.bar); //works
const name = []
name.push("Vinoth");
console.log(name); //works
const age = 100;
age = 20; //Throws Uncaught TypeError: Assignment to constant variable.
console.log(age);
如果常数引用一个对象
,它将始终引用对象
,但是对象
本身可以更改(如果它是可变的)。如果你想拥有一个不可变的对象
,你可以从
在ECMAScript 2015中,let
和const
被提升但未初始化。在变量声明之前引用块中的变量会导致ReferenceError
,因为从块的开始到声明被处理之前,变量处于“暂时死区”
console.log(x); // ReferenceError
let x = 3;
在es6中,当我们使用let或const时,我们必须在使用它们之前声明变量。
例1-
例2-
// this code works as variable j is declared before it is used.
function doSmth() {
j = 9;
}
let j;
doSmth();
console.log(j); // 9
根据ECMAScript®2021
Let和Const声明
- 让和const声明定义作用于正在运行的执行上下文的词典环境的变量
- 变量是在实例化其包含的环境记录时创建的,但在对变量的字典绑定求值之前,不能以任何方式访问变量
- 由带有初始值设定项的词典绑定定义的变量被赋予其I的值
console.log(x); // ReferenceError
let x = 3;
// this will work
u = 10;
var u;
// this will give an error
k = 10;
let k; // ReferenceError: Cannot access 'k' before initialization.
// this code works as variable j is declared before it is used.
function doSmth() {
j = 9;
}
let j;
doSmth();
console.log(j); // 9