使用 var 关键字声明的变量,不管其实际声明位置在何处,都会被视为声明于所在函数的顶部,若是声明不在任意函数内,则视为在全局做用域的顶部。浏览器
function getValue(condition) { if (condition) { var value = "blue"; // 其余代码 return value; } else { // value 在此处可访问,值为 undefined return null; } // value 在此处可访问,值为 undefined } 复制代码
若是你不太熟悉 JS ,或许会认为仅当 condition 的值为 true 时,变量 value 才会被建立。但实际上,value 不管如何都会被建立。 JS 引擎在后台对 getValue 函数进行了调整, 就像这样:安全
function getValue(condition) { var value; if (condition) { value = "blue"; // 其余代码 return value; } else { return null; } } 复制代码
value 变量的声明被提高到了顶部,而初始化工做则保留在原处。这意味着在 else 分支内 value 变量也是可访问的,此处它的值会是 undefined ,由于它并无被初始化。bash
块级声明也就是让所声明的变量在指定块的做用域外没法被访问(在一个函数内部 或 在一个代码块内部)。markdown
let 声明的语法与 var 的语法一致。你基本上能够用 let 来代替 var 进行变量声明,但会将变量的做用域限制在当前代码块中(其余细微差异会在稍后讨论)。因为 let 声明并不会被提高到当前代码块的顶部,所以你须要手动将 let 声明放置到顶部,以便让变量在整个代码块内部可用。并发
function getValue(condition) { if (condition) { let value = "blue"; // 其余代码 return value; } else { // value 在此处不可用 return null; } // value 在此处不可用 } 复制代码
若是一个标识符已经在代码块内部被定义,那么在此代码块内使用同一个标识符进行 let 声明就会致使抛出错误。函数
var count = 30; // 语法错误 let count = 40; 复制代码
在嵌套的做用域内使用 let 声明一个同名的新变量,则不会抛出错误。spa
var count = 30; // 不会抛出错误 if (condition) { let count = 40; // 其余代码 } 复制代码
ES6 中里也可使用 const 语法进行声明。使用 const 声明的变量会被认为是常量( constant ),意味着它们的值在被设置完成后就不能再被改变。正由于如此,全部的 const 变量都须要在声明时进行初始化。试图对以前用 const 声明的常量进行赋值会抛出错误。code
// 有效的常量
const maxItems = 30;
// 语法错误:未进行初始化
const name;
// 抛出错误
const maxItem = 50;
复制代码
常量声明与 let 声明同样,都是块级声明。这意味着常量在声明它们的语句块外部是没法访问的,声明不会被提高,而且在同一个做用域内不能重复定义。orm
使用 const 声明对象比较特殊,const 声明会阻止对于变量绑定与变量自身值的修改,这意味着 const 声明并不会阻止对变量成员的修改。对象
const person = { name: "Nicholas" }; // 工做正常 person.name = "Greg"; // 抛出错误 person = { name: "Greg" } 复制代码
当 JS 引擎检视接下来的代码块并发现变量声明时,它会在面对 var 的状况下将声明提高到函数或全局做用域的顶部,而面对 let 或 const 时会将声明放在暂时性死区内。任何在暂时性死区内访问变量的企图都会致使“运行时”错误(runtime error)。只有执行到变量的声明语句时,该变量才会从暂时性死区内被移除并能够安全使用。
for (var i = 0; i < 10; i++) { process(i); } // i 在此处仍然可被访问 复制代码
for (let i = 0; i < 10; i++) { process(i); } // i 在此处不可访问,抛出错误 console.log(i); 复制代码
由于 var 声明致使了变量提高
在常规的 for 循环中,你能够在初始化时使用 const ,但循环会在你试图改变该变量的值时抛出错误。由于该语句试图更改常量的值。所以,在循环中你只能使用 const 来声明一个不会被更改的变量。
var funcs = []; // 在一次迭代后抛出错误 for (const i = 0; i < 10; i++) { funcs.push(function() { console.log(i); }); } 复制代码
const 变量在 for-in 或 for-of 循环中使用时,与 let 变量效果相同。所以下面代码不会致使出错,由于循环为每次迭代建立了一个新的变量绑定,而不是试图去修改已绑定的变量的值。
var funcs = [], object = { a: true, b: true, c: true }; // 不会致使错误 for (const key in object) { funcs.push(function() { console.log(key); }); } funcs.forEach(function(func) { func(); // 依次输出 "a"、 "b"、 "c" }); 复制代码
在默认状况下使用 const ,而只在你知道变量值须要被更改的状况下才使用 let 。这在代码中能确保基本层次的不可变性,有助于防止某些类型的错误。