let块级作用域
1 { 2 let a = 10; 3 var b = 1; 4 } 5 6 a // ReferenceError: a is not defined. 7 b // 1
for
循环的计数器,就很合适使用let
命令(防止i泄露为全局变量)
1 for (let i = 0; i < 10; i++) { 2 // ... 3 } 4 5 console.log(i); 6 // ReferenceError: i is not defined
下面的代码如果使用var
,最后输出的是10
。
1 var a = []; 2 for (var i = 0; i < 10; i++) { 3 a[i] = function () { 4 console.log(i); 5 }; 6 } 7 a[6](); // 10
如果使用let
,声明的变量仅在块级作用域内有效,最后输出的是6。
1 var a = []; 2 for (let i = 0; i < 10; i++) { 3 a[i] = function () { 4 console.log(i); 5 }; 6 } 7 a[6](); // 6
如果是es5也想输出6的话,必须使用闭包
1 var a = []; 2 for (var i = 0; i < 10; i++) { 3 (function(i){ 4 a[i]=function(){ 5 console.log(i) 6 } 7 })(i) 8 } 9 a[6](); // 10
for
循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域
1 for (let i = 0; i < 3; i++) { 2 let i = ‘abc‘; 3 console.log(i); 4 } 5 // abc 6 // abc 7 // abc
1 // var 的情况 2 console.log(foo); // 输出undefined 3 var foo = 2; 4 5 // let 的情况 6 console.log(bar); // 报错ReferenceError 7 let bar = 2;
不存在变量提升,如上图
1 var tmp = 123; 2 3 if (true) { 4 tmp = ‘abc‘; // ReferenceError 5 let tmp; 6 }
存在全局变量tmp
,但是块级作用域内let
又声明了一个局部变量tmp
,导致后者绑定这个块级作用域,所以在let
声明变量前,对tmp
赋值会报错
1 if (true) { 2 // TDZ开始 3 tmp = ‘abc‘; // ReferenceError 4 console.log(tmp); // ReferenceError 5 6 let tmp; // TDZ结束 7 console.log(tmp); // undefined 8 9 tmp = 123; 10 console.log(tmp); // 123 11 }
1 typeof x; // ReferenceError 2 let x;
如果一个变量没有声明,使用typeof不会报错
1 typeof undeclared_variable // "undefined"
1 function bar(x = y, y = 2) { 2 return [x, y]; 3 } 4 5 bar(); // 报错
1 function bar(x = 2, y = x) { 2 return [x, y]; 3 } 4 bar(); // [2, 2]
// 不报错 var x = x; // 报错 let x = x; // ReferenceError: x is not defined
LET不允许相同作用域重复声明
1 // 报错 2 function () { 3 let a = 10; 4 var a = 1; 5 } 6 7 // 报错 8 function () { 9 let a = 10; 10 let a = 1; 11 }
1 function func(arg) { 2 let arg; // 报错 3 } 4 5 function func(arg) { 6 { 7 let arg; // 不报错 8 } 9 }
内层变量可能覆盖外层变量
1 var tmp = new Date(); 2 3 function f() { 4 console.log(tmp); 5 if (false) { 6 var tmp = ‘hello world‘; 7 } 8 } 9 10 f(); // undefined
1 // 浏览器的 ES6 环境 2 function f() { console.log(‘I am outside!‘); } 3 4 (function () { 5 if (false) { 6 // 重复声明一次函数f 7 function f() { console.log(‘I am inside!‘); } 8 } 9 10 f(); 11 }()); 12 // Uncaught TypeError: f is not a function
等价于
1 // 浏览器的 ES6 环境 2 function f() { console.log(‘I am outside!‘); } 3 (function () { 4 var f = undefined; 5 if (false) { 6 function f() { console.log(‘I am inside!‘); } 7 } 8 9 f(); 10 }()); 11 // Uncaught TypeError: f is not a function
CONST
1 const foo = {}; 2 3 // 为 foo 添加一个属性,可以成功 4 foo.prop = 123; 5 foo.prop // 123 6 7 // 将 foo 指向另一个对象,就会报错 8 foo = {}; // TypeError: "foo" is read-only
1 const a = []; 2 a.push(‘Hello‘); // 可执行 3 a.length = 0; // 可执行 4 a = [‘Dave‘]; // 报错
时间: 2024-10-30 23:45:29