es6:let和var的区别

来源:互联网 发布:mac音频播放器 编辑:程序博客网 时间:2024/06/05 07:20

let和var的区别

基本用法

ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

{  let a = 10;  var b = 1;}a // ReferenceError: a is not defined.b // 1

for循环就非常适合使用let

var a = [];for (var i = 0; i < 10; i++) {  a[i] = function () {    console.log(i);  };}a[6](); // 10

变量i是var命令声明的,在全局范围内都有效

var a = [];for (let i = 0; i < 10; i++) {  a[i] = function () {    console.log(i);  };}a[6](); // 6

变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6.

> for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

for (let i = 0; i < 3; i++) {  let i = 'abc';  console.log(i);}// abc// abc// abc

上面代码正确运行,输出了3次abc。这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。


不存在变量提升

var命令会发生’变量提升’,即变量可以在声明之前使用,值为undefined。

暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响

var tmp = 123;if (true) {  tmp = 'abc'; // ReferenceError  let tmp;}
报错:rect.js:5 Uncaught ReferenceError: tmp is not defined

上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。

ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。

举例:

typeof x; // ReferenceErrorlet x;

上面代码中,变量x使用let命令声明,所以在声明之前,都属于x的“死区”,只要用到该变量就会报错。因此,typeof运行时就会抛出一个ReferenceError。

作为比较,如果一个变量根本没有被声明,使用typeof反而不会报错。

typeof undeclared_variable // "undefined"

这样的设计是为了让大家养成良好的编程习惯,变量一定要在声明之后使用,否则就报错。


不允许重复声明
let不允许在相同作用域内,重复声明同一个变量。

// 报错function () {  let a = 10;  var a = 1;}// 报错function () {  let a = 10;  let a = 1;}

因此,不能在函数内部重新声明参数。

function func(arg) {  let arg; // 报错}function func(arg) {  {    let arg; // 不报错  }}

ES6 的块级作用域 § ⇧

let实际上为 JavaScript 新增了块级作用域。

function f1() {  let n = 5;  if (true) {    let n = 10;  }  console.log(n); // 5}

上面的函数有两个代码块,都声明了变量n,运行后输出5。这表示外层代码块不受内层代码块的影响。如果两次都使用var定义变量n,最后输出的值才是10。


var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从ES6开始,全局变量将逐步与顶层对象的属性脱钩。

var a = 1;// 如果在Node的REPL环境,可以写成global.a// 或者采用通用方法,写成this.awindow.a // 1let b = 1;window.b // undefined

上面代码中,全局变量a由var命令声明,所以它是顶层对象的属性;全局变量b由let命令声明,所以它不是顶层对象的属性,返回undefined。

原创粉丝点击