ES5的作用域
-
全局作用域
全局作用域,就是全局都可以访问的,这个很好理解。
例如在index.js中写入以下代码
var a = "a"; consoel.log(a);//a function (){ console.log(a);//a } fn();这个变量a在全局都可以访问到,它起效的范围是全局,这个就是全局作用域
-
函数内作用域
函数内作用域,即只在本函数内起效
function fn() { var b = "b"; console.log(b);//b } fn(); console.log(b);//b is not definedb只能在函数fn内被访问到
-
弊端
for (var i = 0; i < 10; i++) {
}
console.log(i);//10
直观的感受一下,感觉i是在for里声明的,为什么还会输出来呢?实际上因为ES5没有块级作用域,for循环里的i被泄露到了全局成了全局变量,下面这种情况更为常见
for (var i = 0; i < 10; i++) {
setTimeout(()=>{
console.log(i);//10
},1000*i);
}
console.log('over');
setTimeout将代码段追加到异步任务里,当执行完console.log('over')之后,会去执行异步任务里的console.log(i),而i是全局变量,值为10,所以每次执行setTimeout对应的代码会输出10
ES6的块及作用域
ES6新增了块级作用域。可以简单的理解为一个大括号就是一块,在块内声明的变量只能在块内被访问到。这个时候就需要我们用let或者const来声明变量了。使用let、const和使用var有很大的区别,这里暂时不讨论。
先来看一下怎么使用的
function f1() {
let n = 5;
if (true) {
let n = 10;
console.log(n); // 10 内层的n
}
console.log(n); // 5 当前层的n
}
这里输出n可以看到都是我们期望的值,当然子块可以父块,父块是访问不到子块的。
再看另一个问题
for (let i = 0; i < 10; i++) {
setTimeout(()=>{
console.log(i);//0,1,2,3,4,5,6,7,8,9
},1000*i);
}
console.log('over');
每次执行setTimeout的时候,都传递了一个函数,这个函数创建了一个块,所以每个i都互不影响