var提高以下:es6
function getValue(condition) { if (condition) { var value = "blue"; // 其余代码 return value; } else { // value 在此处可访问,值为 undefined return null; } // value 在此处可访问,值为 undefined }
以下所示:浏览器
function getValue(condition) { if (condition) { let value = "blue"; // 其余代码 return value; } else { // value 在此处不可用 return null; } // value 在此处不可用 }
若是一个标识符已经在代码内部被定义,重复进行let声明会报错安全
var a = 30; //报错 let a = 30;
var count = 30; // 不会抛出错误 if (condition) { let count = 40; // 其余代码 }
// 有效的常量 const maxItems = 30; // 语法错误:未进行初始化 const name;
const person = { name: "Nicholas" }; // 工做正常 person.name = "Greg"; // 抛出错误 person = { name: "Greg" };
if (condition) { const maxItems = 5; // 其余代码 } // maxItems 在此处没法访问
for (var i = 0; i < 10; i++) { process(items[i]); } // i 在此处仍然可被访问 console.log(i); // 10
输出的结果并非预期的值而是10;是由于var声明致使的变量的提高。聪明的你确定会想到使用块级绑定来进行变量声明并发
for (let i = 0; i < 10; i++) { process(items[i]); } console.log(i);
i在此处是否是会正常输出呢,其实不会,在这个例子中会致使报错,为何呢?由于i在此处不可访问。本例中的变量 i 仅在 for 循环内部可用,一旦循环结束,该变量在任意位置都不可访问。函数
咱们在来看看一下代码code
var funcs = []; for (var i = 0; i < 10; i++) { funcs.push(function() { console.log(i); }); } funcs.forEach(function(func) { func(); // 输出数值 "10" 十次 });
你本来可能预期这段代码会输出 0 到 9 的数值,但它却在同一行将数值 10 输出了十次。这是
由于变量 i 在循环的每次迭代中都被共享了,意味着循环内建立的那些函数都拥有对于同一
变量的引用。在循环结束后,变量 i 的值会是 10 ,所以当 console.log(i) 被调用时,
每次都打印出 10 。对象
为了修正这个问题,开发者在循环内使用当即调用函数表达式(IIFEs),以便在每次迭代中
强制建立变量的一个新副本,示例以下:作用域
var funcs = []; for (var i = 0; i < 10; i++) { funcs.push((function(value) { return function() { console.log(value); } }(i))); } funcs.forEach(function(func) { func(); // 从 0 到 9 依次输出 });
let 声明经过有效模仿上例中 IIFE 的做用而简化了循环。在每次迭代中,都会建立一个新的
同名变量并对其进行初始化。这意味着你能够彻底省略 IIFE 而得到预期的结果,就像这样开发
var funcs = []; for (let i = 0; i < 10; i++) { funcs.push(function() { console.log(i); }); } funcs.forEach(function(func) { func(); // 从 0 到 9 依次输出 })
咱们是否会想到这个问题:为何一样的代码使用let声明会致使不同的结果呢?
在循环中let声明每次都建立了一个新的i变量,所以在循环内部建立的函数得到了各自的i副本,而每一个i副本的值都会在每次的循环迭代声明变量的时候肯定了get
var funcs = [], object = { a: true, b: true, c: true }; for (let key in object) { funcs.push(function() { console.log(key); }); } funcs.forEach(function(func) { func(); // 依次输出 "a"、 "b"、 "c" });
本例中的 for-in 循环体现出了与 for 循环相同的行为。每次循环,一个新的 key 变量绑
定就被建立,所以每一个函数都可以拥有它自身的 key 变量副本,结果每一个函数都输出了一个
不一样的值。而若是使用 var 来声明 key ,则全部函数都只会输出 "c" 。
let 声明在循环内部的行为是在规范中特别定义的,而与不提高变
量声明的特征没有必然联系。事实上,在早期 let 的实现中并无这种行为,它是后来
才添加的。
虽然es6没有明确的规范咱们不能在for循环中使用const声明,然而它会根据循环方式的不一样而有不一样的行为,咱们能够在初始化时使用const,可是当循环试图改变变量的值的时候会抛出错误,例如:
var funcs = []; // 在一次迭代后抛出错误 for (const i = 0; i < 10; i++) { funcs.push(function() { console.log(i); }); }
在此代码中, i 被声明为一个常量。循环的第一次迭代成功执行,此时 i 的值为 0 。在
i++ 执行时,一个错误会被抛出,由于该语句试图更改常量的值。所以,在循环中你只能使
用 const 来声明一个不会被更改的变量
而另外一方面, 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" });
这段代码与“循环内的 let 声明”小节的第二个例子几乎彻底同样,惟一的区别是 key 的值在
循环内不能被更改。 const 可以在 for-in 与 for-of 循环内工做,是由于循环为每次迭
代建立了一个新的变量绑定,而不是试图去修改已绑定的变量的值(就像使用了 for 而不是
for-in 的上个例子那样)。
let 与 const 不一样于 var 的另外一个方面是在全局做用域上的表现。当在全局做用域上使 用 var 时,它会建立一个新的全局变量,并成为全局对象(在浏览器中是 window )的一 个属性。