# 变量
# let和作用域
ES6引入了let,用let声明变量,解决了JavaScript没有块级作用域的问题 作用域简单的来说,就是一套寻找变量的规则,用于确定在何处以及如何查找变量。说直白点:这些变量在哪里?它们存储在哪里?编译器如何找到它们?ES6代码之前,只有全局作用域或函数作用域。
当一个块或函数嵌套在另一个函数时,就发生了作用域嵌套。如下代码所示,就有三个嵌套作用域:
function foo(a){
var b =a*2;
function bar (c){
console.log(a,b,c)
}
bar (b*3)
}
foo(2)//2,4,12
- 全局作用域,其中有一个标识符:foo
- foo创建的函数作用域,其中有三个标识符:a,bar和b
- bar创建的函数作用域,其中有一个标识符:c
如何理解全局作用域和函数作用域呢,使用var声明变量时,如果在函数外声明,就是全局变量,任何函数都可以进行使用,这就是全局作用域查找。如果在函数内使用var声明变量,就是函数作用域查找,只能在函数内部进行访问,外部不能进行访问,如下段代码所示:
var a = 12; // 全局作用域都能访问
function myFunction() {
alert(a); // alerts 12
var b = 13;
if (true) {
var c = 14; // 函数内部可以访问
alert(b); // alerts 13
}
alert(c); // alerts 14
}
myFunction();
alert(b); // alerts undefined
因为变量b是在函数内进行声明的,因此函数执行完后,由于垃圾数据回收机制的存在,引擎认为函数执行完了,变量应该进行销毁释放。
如果你在函数内的b标识前忘记写了var关键词,引擎就会自作聪明,在函数外全局作用域为你自动声明变量b,这样在函数外就能访问b变量了(全局作用域)。
因此使用var进行声明时,如果一不小心,你就会声明一个全局作用域的变量,更糟糕的情况还有可能污染一个同名的变量,因此产生的BUG就很难查找。
以下这个例子会更加明显,也是开发者经常会出现的问题,i变量会绑定到外部作用域(函数或全局作用域),污染整个外部作用域:
for (var i = 0; i < 10; i++) {
console.log(i); //依次输出1到9
}
console.log(i);//10
# let 与 var的区别
- 不能重复定义
- 变量不提升
- 块级作用域
let a = 0;
let a = 1; // SyntaxError
var a = 0;
var a = 1;
alert(a); // alerts 1
//在嵌套作用域里进行重新定义变量,虽然变量名相同,但是不是同一变量,如下段代码所示:
var a = 1;
let b = 2;
function myFunction() {
var a = 3; // different variable
let b = 4; // different variable
if(true) {
var a = 5; // overwritten
let b = 6; // different variable
console.log(a); // 5
console.log(b); // 6
}
console.log(a); // 5
console.log(b); // 4
}
myFunction();
console.log(a);
console.log(b);
函数声明和变量声明都会被提升(使用var声明变量,let声明变量将不会被提升)。函数首先会被提升,然后才是变量提升。
解构赋值 →