3

所以我今天开始乱用 JavaScript,遇到了一个有趣的案例,它似乎确信某个东西是一个函数,同时又确信它不是一个函数。这段代码说明了这个问题:

var arr1 = Array(1)
for (i = 0; i < arr1.length; i++) {
    arr1[i] = function(n) { return n + i }
}

var arr2 = Array(1)
for (j = 0; j < arr2.length; j++) {
    arr2[j] = function(n) { return arr1[j](n) }
}

typeof arr2[0] // "function"
arr2[0](2)     // TypeError: Property '1' of object [object Array] is not a function

从这里,您可以将变量分配给arr2[0],并且错误仍然存​​在。我不确定是否需要闭包或数组来复制它。

我的代码有什么问题吗,或者这只是那些 JavaScript 的怪事之一?这不是我特别需要回答的问题,但这有点愚蠢,所以我想知道是否有原因。

4

4 回答 4

3

这实际上确实与闭包有关。

首先,获取以下代码:

for (j = 0; j < arr2.length; j++) {
    arr2[j] = function(n) { return arr1[j](n) }
}

该变量j最初保存值 0,因此arr2[0]设置为对函数的引用。

接下来,j递增,现在的值为 1。这将终止循环。

现在,当函数被调用时

return arr1[j](n)

由于闭包,j最终值仍然为 1。这是该数组中的无效索引。

还有一件事要指出。for循环不会创建新的闭包,因此如果您希望匿名函数将的值包含j该迭代中,则该假设是错误的。j在声明的整个函数中将有一个实例j

于 2013-03-26T04:14:56.493 回答
1

我认为您正在尝试在循环内使用闭包,但它不是那样工作的。

如果您想在循环的每个步骤中使用iand的值j,您可以使用匿名函数,如下所示。

var arr1 = Array(1)
for (i = 0; i < arr1.length; i++) {
    arr1[i] = (function(i){
        return function(n) { 
            return n + i 
        };
    })(i);
}

var arr2 = Array(1)
for (j = 0; j < arr2.length; j++) {
    arr2[j] = (function(j){
        return function(n) { 
            return arr1[j](n)
        }
    })(j);
}

typeof arr2[0] 
arr2[0](2)

演示:小提琴

于 2013-03-26T04:18:51.290 回答
0

它没有做任何奇怪的事情。

你只是在尝试一些不是函数的东西( 的值arr1[1],即undefined)。

于 2013-03-26T04:13:45.797 回答
0

以以下形式初始化数组可能更安全:

var arr1 = [];

或者,如果您使用的是“数组”,您应该像这样初始化它:

var arr1 = new Array();
于 2013-03-26T04:14:52.733 回答