JavaScript中的"new Array(n)"和"Array.prototype.map"的奇怪行为

26 浏览
0 Comments

JavaScript中的"new Array(n)"和"Array.prototype.map"的奇怪行为

我在Firefox-3.5.7/Firebug-1.5.3和Firefox-3.6.16/Firebug-1.6.2中观察到了这个问题。

当我启动Firebug时:

var x = new Array(3)
console.log(x) 
// [undefined, undefined, undefined]
var y = [undefined, undefined, undefined]
console.log(y) 
// [undefined, undefined, undefined]
console.log(x.constructor == y.constructor) // true
console.log( 
  x.map(function() { return 0; })
)
// [undefined, undefined, undefined]
console.log(
  y.map(function() { return 0; })
)
// [0, 0, 0]

这里发生了什么?这是一个bug吗,还是我对如何使用new Array(3)有误解?

0
0 Comments

在使用JavaScript时,我们经常会遇到一些奇怪的问题,其中之一就是使用"new Array(n)"和"Array.prototype.map"时的问题。下面我们来看一下这个问题出现的原因和解决方法。

在ES6中,我们可以使用以下代码来创建一个长度为n的数组,并使用map方法对其进行操作:

[...Array(10)].map((a, b) => a)

在ES6之前,我们可以使用以下代码来创建一个长度为n的数组,并使用fill方法来填充数组:

new Array(10).fill()

这两种方法得到的结果是相同的,都是一个长度为n的数组。

然而,当处理大型数组时,使用ES6的扩展语法可能会出现一些问题,因此最好避免使用这种方法。另一种可以使用的方法是使用keys方法:

[...Array(10).keys()]

对于了解这些方法如何工作的人来说,这些代码可能很容易理解。但对于一些不熟悉这些方法的人来说,可能需要一些解释。

使用"new Array(n)"和"Array.prototype.map"时可能会出现一些奇怪的问题,特别是在处理大型数组时。为了避免这些问题,我们可以使用其他方法来创建和操作数组。

希望以上内容能帮助到那些对这个问题感到困惑的人。

0
0 Comments

JavaScript中的"new Array(n)"和"Array.prototype.map"的奇怪行为

在JavaScript中,使用"new Array(n)"创建一个长度为n的数组时,并不会创建任何元素,所以索引[0]、[1]和[2]并不存在。

而使用Array.prototype.map方法创建一个由3个undefined对象组成的数组时,索引/属性是存在的,但所指向的对象是undefined。

由于map方法是根据数组的索引/属性来运行的,如果没有创建索引/属性,它将无法运行。

根据MDN的定义,map方法会对数组中的每个元素调用提供的回调函数,并按顺序构建一个新数组。回调函数仅在数组中有赋值的索引/属性时被调用,而不会在已删除的索引/属性或从未赋值的索引/属性上调用。因此,在这种情况下,变量x的值没有明确赋值,而变量y的值已经赋值,即使是undefined。

那么,JavaScript是否无法检查它是一个未定义的指针还是指向undefined的指针呢?比如 (new Array(1))[0] === [undefined][0]。

实际上,一个由undefined组成的数组与一个指向undefined对象的指针数组是不同的。一个由undefined组成的数组类似于一个由null值组成的数组,[null, null, null],而一个指向undefined对象的指针数组类似于 [343423, 343424, 343425],指向null、null和null。第二种情况下,指针指向内存地址,而第一种情况下,指针没有指向任何地方。至于这是否是JavaScript的缺陷,可能需要讨论,但不在这里。

你可以通过使用hasOwnProperty方法轻松测试这一点,除非hasOwnProperty本身有bug:(new Array(1)).hasOwnProperty(0) === false,而[undefined].hasOwnProperty(0) === true。实际上,你可以使用in运算符进行相同的测试:0 in [undefined] === true,0 in new Array(0) === false。

在JavaScript中,谈论"undefined指针"会混淆问题。你要寻找的术语是"elisions"。x = new Array(3);等同于x = [,,,];而不是x = [undefined, undefined, undefined]。

我从未声称这两者是相等的,相反,我强调它们是不相等的。在第一种情况下,数组有一个长度但没有内容,映射函数无法运行;而在第二种情况下,虽然对象是undefined,但仍然存在对象,因此映射函数可以运行,只要你不尝试访问对象。问题的提问者在Firebug中看到这两种情况输出相同,但在map函数中的行为不同,所以感到困惑。

我很好奇,从底层(C++领域等)来看,如果一个指针是"undefined指针",它指向的是什么?JavaScript是否分配了一个特殊的内存位置来表示"未定义"。

这个回答中的术语仍然是错误的。map方法不执行其回调函数的原因是new Array(3)没有索引属性达到其长度。关于hasOwnProperty的观点是相关的:map方法将对Object.keys(array)(或.values或.entries等)中的每个条目执行,如果这个列表是空的,map方法将不会执行任何次数。这与"指针"无关。new Array(3)[0]返回undefined的原因是不存在的属性会产生undefined。幸好,现代的调试工具使这种差异更加明显。"undefined对象"是一个自相矛盾的说法。

文章整理自stackoverflow.com的一篇帖子。

0
0 Comments

JavaScript中的"new Array(n)"和"Array.prototype.map"的奇怪问题

在JavaScript中,我们经常需要创建一个指定长度的数组,并对其中的元素进行转换。通常情况下,我们可以使用Array.prototype.map()方法来实现这个目标。例如,我们可以使用以下代码创建一个包含0到9的数字的数组:

let arr = new Array(10).fill(undefined).map((val,idx) => idx);
console.log(arr);

然而,有人尝试使用类似下面的代码来创建这样一个数组:

let arr = new Array(10).map((val,idx) => idx);
console.log(arr);

但是这段代码并没有按预期工作。原因是,当我们使用"new Array(n)"语法创建一个长度为n的数组时,数组中的元素并没有被初始化。因此,Array.prototype.map()方法无法对这些未初始化的元素进行转换。

为了解决这个问题,我们可以使用Array.prototype.fill()方法来填充数组中的元素。我们可以使用任意值来填充数组,甚至可以是undefined。通过使用fill()方法,我们可以将上面的代码修改为:

let arr = new Array(10).fill(undefined).map((val,idx) => idx);
console.log(arr);

除了使用fill()方法之外,另一种解决方法是使用Array.apply()方法。我们可以使用以下代码来创建一个包含0到9的数字的数组:

let arr = Array.apply(null, Array(10)).map((val, idx) => idx);
console.log(arr);

值得注意的是,在使用fill()方法时,我们不需要显式地声明undefined。因此,我们可以将代码进一步简化为:

let arr = new Array(10).fill().map((val,idx) => idx);
console.log(arr);

另外,我们也可以使用Array.from()方法来创建一个指定长度的数组:

let arr = Array.from(Array(10));
console.log(arr);

总结起来,我们可以使用fill()方法、Array.apply()方法或Array.from()方法来解决"new Array(n)"和"Array.prototype.map"的奇怪问题。这些方法都可以填充数组中的元素,使得我们能够使用map()方法对数组进行转换。

0