Javascript变量作用域详解
最近在用babel-node 进行代码转换,也在看ES6相关的东西,看ES6时,真是温故知新的感觉,因此有了这篇博客。
JS作用域规则
- 1.JS大部分情况下没有块级作用域, 除非你使用let
- 2.当你使用var的情况下, JS仅仅支持函数作用域
- 3.不使用var, let声明的变量为全局变量
- 4.不用let情况下, JS中局部变量只能通过var和函数参数声明
1. JS大部分情况下没有块级作用域, 除非你使用let
与很多语言不同, JS在ES6之前并没有块级作用域:
1 2 3 4 5 6 7 8 9 10 11
| function test() { for(var i = 0; i < 10; i++) { } console.log(i); for(let j = 0; j < 10; j++) { } console.log(j); }
|
本例中i并不只存在于for循环的区域中而是存在于整个test函数中. 如果我们用let声明变量i, i则拥有了块级作用域
2. 在你使用var的情况下, JS仅仅支持函数作用域
1 2 3 4 5
| function test() { var a = 'hello' } test() console.log(a)
|
本例中在函数内部声明的变量a的作用域仅限于函数内部, 所以在函数外部我们不能访问到.
3. 不使用var, let声明的变量为全局变量
如果我们把上面的例子中的var去掉会发生什么呢?
1 2 3 4 5
| function test() { a = 'hello' } test() console.log(a)
|
4. 不用let情况下, JS中局部变量只能通过var和函数参数声明
由上面的分析我们知道, 函数内部声明的变量的作用域为函数内也就是属于局部变量.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| for (var i = 0; i < 10; i++){ setTimeout(function(){ console.log(i); }, 1000); } for (var i = 0; i < 10; i++){ setTimeout(function(i){ console.log(i); }, 1000, i); } for (var i = 0; i < 10; i++){ setTimeout(function(i){ console.log(i); }.bind(null, i), 1000); } var cb = function(i) { return function() { console.log(i) } } for (var i = 0; i < 10; i++){ setTimeout(cb(i), 1000); }
|
后三个例子看似无关联其实原理是一致的: 把变量当作函数参数传入函数, 这样变量就在函数中有了局部作用域而非全局作用域.在ES6时代我们只需要通过let创建拥有快级作用域的变量就可以轻松解决上述问题了.
1 2 3 4 5 6
| for (let i = 0; i < 10; i++){ setTimeout(function(){ console.log(i); }, 1000); }
|