1
zztczcx 2013-07-13 15:56:51 +08:00
因为这里只有一个作用域就是 全局作用域。在第一个for循环里,闭包的作用域是全局的域(也就是运行这个函数的域),第二个for仍然是在同一个域中。
我看你上一个帖子,那个闭包的创建你用的就挺对的啊。 |
2
bakac 2013-07-13 15:57:57 +08:00
var i = 0;
for (i = 0; i < 10; i ++){ dofun[i] = function(){ return i; } } console.log(i); // i = 10; for (i = 0; i < 10; i++){ //i 0 -> 9 console.log(dofun[i]()); } 因为公用了 都引用了i ,而是第2个for又把i的值覆盖 |
3
pythonee OP |
4
Golevka 2013-07-14 01:23:59 +08:00
@pythonee 所以说javascript中for从句的scoping是一个和C++/C#/Java程序员直觉很不一样的设计————你在for(var i..中定义的i出了for之后还是可用的, 也就是说你在for里面定义的那个i是全局的.
|
5
chemzqm 2013-07-14 06:18:01 +08:00
|
6
pythonee OP |
8
Golevka 2013-07-14 14:16:18 +08:00 1
@pythonee 人家ECMA-262 13.2明确规定的lexical scoping的东西怎么一下子变成求值时解析了? 你在global scope创建的function object, F.[[Scope]]自然引用的是全局作用域. 并且你也知道所有的inner function都共享同一个parent scope, 那么parent scope里变量的值变了自然会影响closure的求值结果.
|
10
heroicYang 2013-07-14 14:38:46 +08:00
@Golevka 点赞,非常赞同!
|
11
clowwindy 2013-07-14 14:41:43 +08:00
JavaScript 是 function scoping + static scoping,变量名绑定哪个变量是编译时就确定的。
|
12
undozen 2013-07-14 14:56:45 +08:00
楼主不如看看我之前写过的文章?
http://zh.undozen.com/2013/10 |
14
Golevka 2013-07-14 17:27:56 +08:00
我感觉LZ是被误导了. 刚才点开LZ贴出的链接, 于是我感觉微软的那个MVP碉堡了.
"函数是不是值得来锁定一个变量,是看该变量在调用这个函数的时候,是不是能在上下文作用域中找到这个变量,如果无法在调用时找到这个变量,内部函数就会锁住它,否则就不会锁住,至少表面上是这样的。" 我擦咧? 难道我计算一个函数的free variable时还要关心它所有的call site么? 还有和"创建"函数的时机相关的说明我都不知该从哪吐嘈了. |
15
pythonee OP |
16
pythonee OP @Golevka
其实我觉得 那个mvp说的也没有问题的样子,它并不是说关心call site,是说在 ()或 return的时候会锁定变量,假如不是像他说的那样的话,按理来说,第一个for就会求值的话,那么这时候 闭包里的 i 都是10了,也就没有第二个for什么事了 |
17
Golevka 2013-07-14 23:42:24 +08:00 1
@pythonee .................................
ECMAScript中的closure"锁定"的不是变量的值, 而是environment; 并且"锁定"的时机也不是在()/return/求值时, 而是在"定义"时. 不信你翻一下262看看在遇到"FunctionDeclaration"这条产生式时编译器需要做什么动作? Entering Function Code时又要做什么动作? 顺便SICP的3.2 The Environment Model of Evaluation也可拿来作为参考, 因为那里描述的也是带upward的模型, 也即js-er所谓的scope chaining. |
18
pythonee OP @Golevka
哦,这下总算找到正统了,我之前还看了一篇 javascript执行上下文的文章,这里的环境应该就是指的上下文吧,上下文的建立应该是在定义时,赋值是在执行时。哈哈,非常感谢你的回答,我突然觉得javascript很多概念挺统一的啊,之前被它的变化多端弄得神魂颠倒 |
19
Mutoo 2013-07-15 09:45:26 +08:00
var dofun = [];
var i = 0; // global i for (i = 0; i < 10; i++) { (function() { var that_i = i; // encloure_i dofun[i] = function() { return that_i; } })(); } console.log(i); // i = 10; for (i = 0; i < 10; i++) { //i 0 -> 9 console.log(dofun[i]()); } |