之前看过汤姆大叔的博客翻译的js the core
- 变量对象 http://www.cnblogs.com/TomXu/archive/2012/01/16/2309728.html
- 闭包 http://www.cnblogs.com/TomXu/archive/2012/01/31/2330252.html
- 原文 http://dmitrysoshnikov.com/ecmascript/javascript-the-core/
对for循环中出现的问题可以做出解释
var data = [];
for (var k = 0; k < 3; k++) {
data[k] = function () {
alert(k);
};
}
为什么直接data[k] = function(){ alert(k) }这样做k总是3, 因为闭包 data[0] data[1] data[2]的 [[scope]]属性是一样的, 他们是在同一个上下文中创建出的闭包, 他们
- data[0].scope = [ data0Context.VO, globalContextVO ]
- data[1].scope = [ data1Context.VO, globalContextVO ]
- data[2].scope = [ data2Context.VO, globalContext.VO ] 可以看到除了第一个是它们自己的VO外, 后面都是一样的, 他们引用的k不存在于他们自己的VO对象中, 由于外面k修改, 他们都跟着变了.
为什么加一层自执行函数可以.
for (var k = 0; k < 3; k++) {
(function temp(k){
data[k] = function () {
alert(k);
};
})(k);
}
此时他们的scope属性如下
- data[0].scope = [ data0Context.VO, tempContext.VO={ k:0}, globalContext.VO ]
- data[1].scope = [ data1Context.VO, tempContext.VO={ k:1}, globalContext.VO ]
- data[2].scope = [ data2Context.VO, tempContext.VO={ k:2}, globalContext.VO ] 可以看到他们的scope chain中引用到k的地方是没有重合的, 后修改for循环中的k是不会影响到他们scope chain中的k值的.
问题来了 http://dmitrysoshnikov.com/ecmascript/javascript-the-core/comment-page-3/#comment-173907
var data = [];
for (let k = 0; k < 3; k++) {
data[k] = function () {
alert(k);
};
}
data[0](); // 0
data[1](); // 1
data[2](); // 2
阮一峰对ES6 let类似的问题有个解释, 块级作用域, 这个我也知道, 但解决不了我的问题 http://es6.ruanyifeng.com/#docs/let
我的想法是:
- data[0].scope = [ data0Context.VO, blockContext.VO={ k }, globalContext.VO ]
- data[1].scope = [ data1Context.VO, blockContext.VO={ k }, globalContext.VO ]
- data[2].scope = [ data2Context.VO, blockContext.VO={ k }, globalContext.VO ]
k存在于 let-for的块级作用域中, 而且是公共的, 就是引用的同一个k, 结果应该也是与 var 相同, 但是测试结果不是这样的, 遂求解答?