var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6
想不明白了, 谁能帮忙解释下这是为啥呢?
![]() | 1 JohnLou 2016-11-15 23:29:29 +08:00 我刚看了这个,因为 var 的作用域只能是函数和全局,而 let 是块,也就是{},所以对于 let , for 循环一次, i 就在那个循环里起作用而已。 |
![]() | 2 chemzqm 2016-11-15 23:32:43 +08:00 你或许需要一本 exploring es6 |
3 miketeam 2016-11-15 23:38:03 +08:00 via iPhone 总是喜欢把事情搞得这么复杂,所以一点都不喜欢了 js |
![]() | 4 nanxiaobei 2016-11-15 23:58:22 +08:00 用 var ,每个 function 都保存着 i 的同一个变量对象,为 10 。 用 let ,是块级作用域,每次的 i 是独立的,大概是这样吧。 |
![]() | 5 brooky OP @JohnLou 用 var 声明的话数组里面存的是 [ funciton(){console.log(i)}, funciton(){console.log(i)}...] 用 let 声明数组里面的即是[ function(){console.log("1")}, function(){console.log("2")} ....]? |
![]() | 6 jswh 2016-11-16 00:09:00 +08:00 |
![]() | 8 JohnLou 2016-11-16 00:30:14 +08:00 via iPhone @brooky 不是很准确,可以理解为这样[{let i=0;}, {let i =1}], i ++之后就新起一个块。 |
![]() | 9 SoloCompany 2016-11-16 01:08:54 +08:00 你应该这样理解 本来不应该有 var 和 let 的 因为他们其实除了作用域以外没有任何区别 但由于历史原因, var 的作用域泄露的问题被吐槽太多了,又不得不兼容,所以才产生了 let js 三种变量声明方式 x; var x; let x; 如果可以用更合适的关键字修饰符的话,就是等同于 global x; (前提是变量没有在任何作用域中被定义) function local x; local x; |
![]() | 10 ByZHkc3 2016-11-16 01:17:10 +08:00 作用域的区别, let 只在当前循环或函数里有效,这等同于再函数里 var 了一样。 |
![]() | 11 brooky OP ```` var tmp = new Date(); function f() { console.log(tmp); if (false) { var tmp = "hello world"; } } f(); // undefined ```` 又来个问题, 自学真的很不行是不是, 求老司机带带 付费指导 |
![]() | 12 baconrad 2016-11-16 01:56:29 +08:00 因 var 的量明被提前, 先理後, 再看就比容易理解. ``` var a = []; var i; for ( i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10 ``` ``` var tmp = new Date(); function f() { var tmp; console.log(tmp); if (false) { tmp = "hello world"; } } f(); // undefined ``` |
![]() | 13 geekaven 2016-11-16 02:27:52 +08:00 作用域,变量提升。 |
![]() | 14 geekaven 2016-11-16 02:28:34 +08:00 可以看看《你不知道的 Javascript 》 第一卷 1 , 2 , 3 , 4 章 |
![]() | 15 Sivan 2016-11-16 02:32:41 +08:00 建议楼主先学一下基础知识再去学 ES6 相关改进。 |
![]() | 17 yyfearth 2016-11-16 07:00:50 +08:00 @brooky 所以两者不要混用 let 是 block scope 和大多数语言一样 所以最近才出现 减少问题的发生 var 是 function scope 由于历史原因 对于很多人来说 非常容易混淆 所以你能用 let 的情况下 只用 let 如果你要考虑浏览器兼容性的情况下 就只用 var 不要混用 把自己搞糊涂 |
18 kitalphaj 2016-11-16 07:27:00 +08:00 难道不是还有一个 const 么。。。。所以一共是四种修饰方式么? var, let, const, 和空。。。 |
![]() | 19 WildCat 2016-11-16 07:44:14 +08:00 via iPhone |
![]() | 20 murmur 2016-11-16 08:05:13 +08:00 目前 var 和 let 没任何区别 本来我以为 babel 会把 let 的变量都搞到函数里隔绝作用域 结果如果没重名的话就是把 var 改成 let 如果有重名就在 let 的变量下家个下划线。。 |
21 ryanzyy 2016-11-16 08:48:36 +08:00 for (var i = 0; i < 10; i++) console.log(i); i -> 10 for (let i = 0; i < 10; i++) console.log(i); i -> undefined |
![]() | 22 ChefIsAwesome 2016-11-16 09:04:58 +08:00 |
![]() | 23 misaka19000 2016-11-16 09:09:26 +08:00 let 这玩意是不是出自 lisp |
24 ssehacker 2016-11-16 09:22:35 +08:00 13 楼正解,就这两点。 |
![]() | 25 4641585 2016-11-16 09:31:50 +08:00 |
![]() | 26 JohnLou 2016-11-16 11:31:16 +08:00 补充一下我 8 楼说的,楼主是否明白了呢,执行下下面的代码。 for(let i = 0;i < 3;i ++) { a[i] = function () {console.log(i);} setTimeout(function () {i = i * 1000}, 1000); } a[1]() // 1000 a[2]() // 2000 |
27 coldsnap 2016-11-16 11:31:33 +08:00 @murmur 你把楼主用 let 的语法用 babel 转了试试,通过新建一个 loop 函数的确给了 i 作用域,得到也是期望的结果;改名能避免变量提升带来的问题,这样做没问题。例如: { let a = 'a' } console.log(a) 会被编译成 { var _a = 'a' } console.log(a) 你得到的结果和你在支持 let 语法的宿主环境中一样。 而且有些情况根本不需要编译,例如写 electron 和 node 。准确来说你应该说对你没区别。 |
28 SuperMild 2016-11-16 11:36:28 +08:00 自从有了 let 之后,好像提倡不要用 var 了,绝大多数情况下用 let 就够了。如果一时之间觉得比较乱,建议不要去管 var ,只管用 let 就好了,没有必要执着于两者的区别(过一段时间回头看很可能会豁然开朗)。 |
![]() | 29 chnhyg 2016-11-16 11:47:51 +08:00 var 与 let - let 是更完美的 var 。 - let 声明的变量拥有块级作用域。 - let 声明的全局变量不是全局对象的属性。 - 形如 for(let I …) 的循环在每次迭代时都为 I 创建新的绑定。 - let 声明的变量直到控制流到达该变量被定义的代码行时才会被装载,所以在到达之前使用该变量会触发错误。不可访问的这段时间变量一直处于作用域中,但是尚未装载,它们位于临时死区(Temporal Dead Zone)中。 - 用 let 重定义变量会抛出一个语法错误。 |
30 vlxer 2016-11-16 14:54:20 +08:00 要理解这个,首先要理解词法作用域。 * 定义一个函数的时候,函数会保存当前作用域 * 函数执行的时候,会创建一个新的作用域,用于存放函数参数和局部变量,同时新的作用域指向函数保存的作用域,构成作用域链 因此,第一个例子中,由于没有块级作用域,循环里的所有函数都是共享同一个作用域的, a[0] == a[1] == ... == a[9] == i == 10 。 第二个例子中,有块级作用域,等价于: ```js var a = []; for (var i = 0; i < 10; i++) { (function(i) { a[i] = function() { console.log(i); }; })(i); } a[6](); // 6 ``` 通过查看 babel 的转换也可以看出: http://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=latest%2Creact%2Cstage-2&experimental=false&loose=false&spec=false&code=var%20a%20%3D%20%5B%5D%3B%0Afor%20(let%20i%20%3D%200%3B%20i%20%3C%2010%3B%20i%2B%2B)%20%7B%0A%20%20a%5Bi%5D%20%3D%20function%20()%20%7B%0A%20%20%20%20console.log(i)%3B%0A%20%20%7D%3B%0A%7D%0Aa%5B6%5D()%3B%20%2F%2F%206&playground=true 不明白问我,付费指导。 |
![]() | 31 anthozoan77 2016-11-28 22:47:32 +08:00 IIFE |