我希望有人可以向我解释下面的代码中发生了什么。我发现很难理解为什么这种闭包对原语和引用的处理方式不同。我希望这里缺少明显的东西。
function returnFunction(x, y) {
return function() {
alert("x:" + x + " - nb of elements in y:" + y.length);
};
}
var f = 0;
var g = [];
var h = [];
for(var i = 0; i < 3; i++) {
f += 1;
g.push(i);
h.push(returnFunction(f, g));
}
for(var i = 0; i < 3; i++) {
h[i]();
}
// this is what gets returned
// x:1 - nb of elements in y: 3
// x:2 - nb of elements in y: 3
// x:3 - nb of elements in y: 3
// why do x and y get treated differently by js in this case?
Run Code Online (Sandbox Code Playgroud)
这是因为,上下文被绑定到引用,而不是被调用/创建时绑定到引用的快照。
让我们逐段浏览代码以更清晰
for(var i = 0; i < 3; i++) {
f += 1;
g.push(i);
h.push(returnFunction(f, g));
}
Run Code Online (Sandbox Code Playgroud)
上面的循环执行3次,每次将一些值放入garray和harray中。
因此,让我们进入内部,填充值。在此之前,请使用下面的代码明确说明。
function returnFunction(x, y) {
return function() {
alert("x:" + x + " - nb of elements in y:" + y.length);
};
}
Run Code Online (Sandbox Code Playgroud)
一次调用上面的函数,将返回一个函数,再次调用该函数,意味着您第一次收到的引用都将显示警告。总之(returnFunction(5,[4,5,6])())会显示一个警报
"x:5 - nb of elements in y: 3"。//看起来好像y正在接受数组参数,因为在警报中,我们具有y.length属性。
价值填充
loop_number:
1 .----f = 1----g = [1]----h [用(1,array-g [1])调用时的返回函数]
2 .----f = 2----g = [1,2]----h [用(1,array-g [1])调用时返回函数,用(2,数组-g [1,2])]
3 .----f = 3----g = [1,2,3]----h [使用(1,array-g [1])调用时返回函数,使用(()调用时返回函数2,array-g [1,2]),使用(3,array-g [1,2,3])]调用时返回函数
最后
for(var i = 0; i < 3; i++) {
h[i]();
}
Run Code Online (Sandbox Code Playgroud)
我们正在遍历h数组,即h在上面的解释中,在循环3处数组中具有的值。它具有已经具有上下文值的内部功能。即,它知道每次调用时是什么x,什么是y调用。记住,第二个参数是h我们发送的数组引用。
因此,如果我们执行像这样的函数h[i](),它将以第一个x的主值和y数组引用执行。即使当我们调用returnFunctionwith g数组并且它只有一个值时,返回的函数仍与引用绑定,而不是该快照具有的引用。
所以输出是打印数组大小为// x:1 - nb of elements in y: 3
在执行时,第二和第三循环也是如此returnFunction。