JavaScript:函数数组出现TypeError错误

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中的一种奇怪现象?这不是我特别需要答案的东西,但它有点愚蠢,所以我想知道是否有原因。

1
为什么要使用Array(1)和循环,而不是var arr1 = [function(n) { return n + 1;}]; - Matt Ball
可能是重复的问题:Javascript循环内部的闭包 - 简单实用的例子 - bfavaretto
这最初是在我尝试使用闭包数组来处理循环索引时发生的,所以我就保持了这种方式。 - user1392737
此外,@bfavaretto:这有点像我最初测试的内容,结果与我想的不同(每个原则的基础是相同的)。因此,我愿意承认这是一个重复的问题。 - user1392737
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变量存在。

啊,这很有道理(我学到了越界索引返回undefined而不是抛出错误)。感谢您的快速回答。 - user1392737
是的,数组就像任何其他对象一样成为属性包。如果您愿意,没有任何阻止您设置arr2[50]arr2['bananas'] - Mike Christensen

1
我认为你想在循环内部使用闭包,但它不是这样工作的。
如果你想在每个循环步骤中使用ij的值,你需要使用如下所示的匿名函数。
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)

演示:Fiddle


0

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

你只是试图执行一个不是函数的操作(arr1[1] 的值为 undefined)。


0

在编程中,初始化数组的形式最好采用以下方式:

var arr1 = [];

如果你正在使用“Array”,那么你应该像这样初始化它:

var arr1 = new Array();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接