var let const

var声明的变量挂在在全局window上面,let和const声明的变量不在window上。

let 语句声明一个块级作用域的局部变量,并可以初始化为一个值(可选)。

let a = 1;

let 允许你声明一个作用域被限制在块作用域中的变量、语句或者表达式。与 var 关键字不同的是,var 声明的变量作用域是全局或者整个函数块的。 var 和 let 的另一个重要区别,let 声明的变量不会在作用域中被提升,它是在编译时才初始化(参考下面的暂时性死区)。

就像 const 一样,let 不会在全局声明时(在最顶层的作用域)创建 window 对象的属性。

通过在使用 let 变量的作用域顶部声明它们,可以避免很多问题,但这样做可能会影响可读性。

与 var 不同的是,let 只是开始声明,而非一个完整的表达式。这意味着你不能将单独的 let 声明作为一个代码块的主体(因为声明的变量无法被访问)。

if (true) let a = 1; // SyntaxError: Lexical declaration cannot appear in a single-statement context

在全局作用域中,let 和 var 不一样,它不会在全局对象上创建属性。例如:

var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined

在同一个函数或块作用域中重复声明同一个变量会抛出 SyntaxError。

if (x) {
  let foo;
  let foo; // SyntaxError thrown.
}

在 switch 语句中也会触发这个错误,因为它是同一个块作用域。

let x = 1;

switch(x) {
  case 0:
    let foo;
    break;
  case 1:
    let foo; // SyntaxError for redeclaration.
    break;
}

然而,需要特别指出的是,一个嵌套在 case 子句中的块会创建一个新的块作用域的词法环境,就不会产生上诉重复声明的错误。

let x = 1;

switch(x) {
  case 0: {
    let foo;
    break;
  }
  case 1: {
    let foo;
    break;
  }
}

暂时性死区

从一个代码块的开始直到代码执行到声明变量的行之前,let 或 const 声明的变量都处于“暂时性死区”中。

当变量处于暂时性死区之中时,其尚未被初始化,尝试访问变量将抛出 ReferenceError。当代码执行到声明变量所在的行时,变量被初始化为一个值。如果声明中未指定初始值,则变量将被初始化为 undefined。

与 var 声明的变量不同,如果在声明前访问了变量,变量将会返回 undefined。以下代码演示了在使用 let 和 var 声明变量的行之前访问变量的不同结果。

{ // TDZ starts at beginning of scope
  console.log(bar); // undefined
  console.log(foo); // ReferenceError
  var bar = 1;
  let foo = 2; // End of TDZ (for foo)
}

使用术语“temporal”是因为区域取决于执行顺序(时间),而不是编写代码的顺序(位置)。例如,下面的代码会生效,是因为即使使用 let 变量的函数出现在变量声明之前,但函数的执行是在暂时性死区的外面。

{
  // TDZ starts at beginning of scope
  const func = () => console.log(letVar); // OK

  // Within the TDZ letVar access throws `ReferenceError`

  let letVar = 3; // End of TDZ (for letVar)
  func(); // Called outside TDZ!
}

暂时性死区与 typeof

如果使用 typeof 检测在暂时性死区中的变量,会抛出 ReferenceError 异常:

// results in a 'ReferenceError'
console.log(typeof i);
let i = 10;

这与使用 typeof 检测值为 undefined 的未声明变量不同:

// prints out 'undefined'
console.log(typeof undeclaredVariable);

暂时性死区和词法作用域
以下代码会导致 ReferenceError:

function test() {
  var foo = 33;
  if(foo) {
    let foo = (foo + 55); // ReferenceError
  }
}
test();

由于外部变量 foo 有值,因此会执行 if 语句块,但是由于词法作用域,该值在块内不可用:if 块内的标识符 foo 是 let foo。表达式 (foo + 55) 会抛出 ReferenceError 异常,是因为 let foo 还没完成初始化,它仍然在暂时性死区里。

在以下情况下,这种现象可能会使您感到困惑。let n of n.a 已经在 for 循环块的私有范围内,因此,标识符 n.a 被解析为位于指令本身(let n)中的“n”对象的属性“a”。

在没有执行到它的初始化语句之前,它仍旧存在于暂时性死区中。

function go(n) {
  // n here is defined!
  console.log(n); // Object {a: [1,2,3]}

  for (let n of n.a) { // ReferenceError
    console.log(n);
  }
}

go({a: [1, 2, 3]});

其它情况

用在块级作用域中,let 将变量的作用域限制在块内,而 var 声明的变量的作用域是在函数内。

var a = 1;
var b = 2;

if (a === 1) {
  var a = 11; // the scope is global
  let b = 22; // the scope is inside the if-block

  console.log(a);  // 11
  console.log(b);  // 22
}

console.log(a); // 11
console.log(b); // 2

然而,var 与 let 合并的声明方式会抛出 SyntaxError 错误,因为 var 会将变量提升至块的顶部,这会导致隐式地重复声明变量。

let x = 1;

{
  var x = 2; // SyntaxError for re-declaration
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值