let const 与 var

ES6 的一个重要特性就是有了块的概念,引入了let、const声明变量,在刚开始接触这两个标识符的时候,就当作var来用的,可是他们之间实际上是有不少差异的。本篇整理了一下,简单的地方只是列了一个提纲,文末还有他们之间的区别,当用到的时候能够回来看。node

js中对于未声明的变量会报语法错误,对于未初始化值的变量会报undefined。编程

一、var声明及变量提高机制

做用域:函数做用域、全局做用域浏览器

变量提高:变量的==声明位置==提高到当前做用域顶部,可是变量的==初始化位置==不变。安全

二、块级声明

块级声明 ----->块级标识符----->let、constbash

----->块级做用域(亦称词法做用域):指函数内部、{}之间的区域函数

块级变量只在代码块内有效,代码块外当即销毁。ui

2.1 let声明

2.2 禁止重命名

2.3 const声明

要求声明时必须进行初始化,且值一旦被设定后不可更改。spa

可是对于js对象而言, const声明不容许修改绑定,可是容许修改绑定的值设计

2.4 临时死区

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

总之,在代码块内,使用let命令声明变量以前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。

临时死区内,使用该变量,如:typeof,都会报语法错误; 若是没有造成临时死区,使用该变量,typeof,则不会报错。 例:2.4.二、2.4.3

2.4.1
var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}
复制代码
2.4.2
typeof x; // ReferenceError
let x;
复制代码

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

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

2.4.3
typeof undeclared_variable // "undefined"
复制代码

上面代码中,undeclared_variable是一个不存在的变量名,结果返回“undefined”。因此,在没有let以前,typeof运算符是百分之百安全的,永远不会报错。如今这一点不成立了。这样的设计是为了让你们养成良好的编程习惯,变量必定要在声明以后使用,不然就报错。

有些“死区”比较隐蔽,不太容易发现。

function bar(x = y, y = 2) {
  return [x, y];
}

bar(); // 报错
复制代码

上面代码中,调用bar函数之因此报错(某些实现可能不报错),是由于参数x默认值等于另外一个参数y,而此时y尚未声明,属于“死区”。若是y的默认值是x,就不会报错,由于此时x已经声明了。

function bar(x = 2, y = x) {
  return [x, y];
}
bar(); // [2, 2]
复制代码

另外,下面的代码也会报错,与var的行为不一样。

// 不报错
var x = x;

复制代码
// 报错
let x = x;
// ReferenceError: x is not defined
复制代码

上面代码报错,也是由于暂时性死区。使用let声明变量时,只要变量在尚未声明完成前使用,就会报错。上面这行就属于这个状况,在变量x的声明语句尚未执行完成前,就去取x的值,致使报错”x 未定义“。

2.5 循环中的块做用域绑定

var:for与 for in、 for of let:for与 for in、 for of const:for与 for in、 for of

2.6 全局做用域绑定

三、块级绑定最佳实践

默认使用const,只在确实须要改变变量的值时才使用let。

四、块级标识符与var的区别:

一、变量提高:var声明的变量会变量提高,而块级标识符不会。

二、变量重命名:var容许同一个做用域下变量重名,可是会覆盖,而块级标识符不容许在同一个做用域下变量重名。

三、全局做用域绑定: var声明的变量,若是和全局对象相同,则仍然是覆盖原则。 而块级标识符和全局对象没有任何关系。

全局对象:浏览器环境中是window,node环境中是global。

var a = 2;
var a = 3; // a=3

复制代码
相关文章
相关标签/搜索