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
|