我已经玩了一段时间的ES6,我注意到,而变量声明与var被提升的预期…

console.log(typeof name); // undefined
var name = "John";

...使用let或const声明的变量似乎在提升时存在一些问题:

console.log(typeof name); // ReferenceError
let name = "John";

and

console.log(typeof name); // ReferenceError
const name = "John";

这是否意味着用let或const声明的变量不会被提升?这到底是怎么回事?let和const在这个问题上有什么区别吗?


当前回答

来自MDN web文档:

在ECMAScript 2015中,let和const被提升但没有初始化。在变量声明之前在块中引用变量会导致ReferenceError,因为从块开始直到声明被处理,变量都处于“临时死区”。

console.log(x); // ReferenceError
let x = 3;

其他回答

来自MDN web文档:

在ECMAScript 2015中,let和const被提升但没有初始化。在变量声明之前在块中引用变量会导致ReferenceError,因为从块开始直到声明被处理,变量都处于“临时死区”。

console.log(x); // ReferenceError
let x = 3;

Let和const也被提升。 但是,由于以下原因,如果使用let或const声明的变量在初始化之前被读取,则会引发异常。

与var不同,它们在提升时不会使用默认值初始化。 在完全初始化之前,不能读/写它们。

ES6引入了Let变量,用于块级作用域。在ES5之前,我们没有块级作用域,所以在块中声明的变量总是提升到函数级作用域。

基本上作用域指的是在你的程序中你的变量是可见的,这决定了你可以在哪里使用你声明的变量。在ES5中,我们有全局作用域、函数作用域和try/catch作用域,在ES6中,我们还使用Let来获得块级作用域。

When you define a variable with var keyword, it's known the entire function from the moment it's defined. When you define a variable with let statement it's only known in the block it's defined. 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"]);

如果运行代码,可以看到变量j只在循环中已知,而不是在循环前后已知。然而,我们的变量i在整个函数中是已知的,从它被定义的那一刻起。

使用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)
}

第一个for循环总是打印最后一个值,让它创建一个新的作用域并绑定新的值,打印出1,2,3,4,5。

对于常量,它的工作原理基本类似于let,唯一的区别是它们的值不能改变。在常量中,允许突变,但不允许重新赋值。

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);

如果一个常量指向一个对象,它将始终指向该对象,但对象本身可以被改变(如果它是可变的)。如果你想要一个不可变的对象,你可以使用object .freeze([])

引用ECMAScript 6 (ECMAScript 2015)规范的let和const声明部分,

变量是在实例化包含它们的lexicalenvironment时创建的,但在变量的LexicalBinding被求值之前,不能以任何方式访问变量。

因此,回答你的问题,是的,let和const提升,但在运行时评估实际声明之前不能访问它们。

在es6中,当我们使用let或const时,我们必须在使用它们之前声明变量。 如。1 -

// this will work
u = 10;
var u;

// this will give an error 
k = 10;
let k;  // ReferenceError: Cannot access 'k' before initialization.

如。2 -

// this code works as variable j is declared before it is used.
function doSmth() {
j = 9;
}
let j;
doSmth();
console.log(j); // 9