JavaScript中只添加元素而无需使用push函数来改变数组大小的方法。

10

我知道改变数组大小的通用方法是使用.push()

然而,今天我在AngularJS中看到了一段代码,类似于这样:

var service = {
   pages: [],
   doSmth: doSmth
};

doSmth();

function doSmth() {
   service.pages[1] = "abc";
   service.pages[5] = "def";
}

我在浏览器上运行了调试器,发现在调用 doSmth() 之前,pages[1] 是未定义的,但在调用后,没有出现任何错误就给 pages[1] 赋值了。

这是如何可能的呢?


3
因为已经在 "pages:[]" 中初始化了页面。如果没有 "pages:[]",您将看到未定义的错误。 - tanjir
5
给数组下标赋值时,如果下标等于或超过数组长度,数组会被重新调整大小以适应新的下标。 - Ry-
你期望的行为是什么?请记住,function doSmth 是被提升的。 - NicolasMoise
1
你可以随时在数组的任何索引处添加一个元素,它会“调整大小”(到目前为止,长度将显示为最大索引+1)以适应。push函数只是一种方便的方法,用于将元素添加到myarray[myarray.length] - Matt Burland
1
@PTN:在Javascript中没有越界异常。 - Matt Burland
显示剩余2条评论
3个回答

21

这正是 JavaScript 所允许的神奇之处。如果你来自 Java 或 C 等其他语言,可能会觉得这个想法很奇怪,但你可以随时设置数组中任何索引的值,并且数组将扩展到该大小!

考虑以下代码:

var t = [];
t.length === 0;
t[10000] = 'value';
t.length === 10001;

JavaScript会在幕后处理这个问题。值得一提的是,这种行为并不局限于JavaScript。其他解释性语言也有类似的情况。例如,Ruby也允许你这样做。

此外,在JavaScript中,length是数组的可写属性,因此您可以轻松地截断或清除整个数组:

var t = [1];
t[4] = 0;
t === [1, undefined, undefined, undefined, 0];
t.length = 2;
t === [1, undefined];
t.length = 0;
t === [];

将长度设置为0是清空数组的最快和最简单的方法之一。这可能不是最直观的解决方案,但这是我首选的方法。


4
注意:数组可能实际上并没有扩展。它的行为就像已经扩展了一样,但实际上,根据实现方式,在内部它可能并没有分配任何额外空间。 - Matt Burland
3
所有这些内容在规范 http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.5.1 中得到了正式描述。 - Alexander Manekovskiy

3
在JavaScript中,数组只是带有一些特殊属性的对象。本质上,它们只是具有正整数属性名称的对象。虽然还存在其他一些关键差异,但是基本思想是你可以这样做:
var obj = { };
obj['1'] = 'abc';

所以,您可以使用数组来做同样的事情。

但是! 您不应该这样做。现代JavaScript引擎通常通过快速、本地化实现来优化数组。通过设置当前未分配的索引将使您的代码变得更像对象,这会使其变得更加缓慢。


但事实并非如此发生。 - CoderPi
var obj = { }; <- 你正在初始化一个对象,而不是数组。obj = [] 是数组。 - tanjir
@CodeiSir:以什么方式? - Ry-
@minitech 看看我的答案,它不是同一个命名空间。 - CoderPi
@tanjir,我明白,数组只是JS对象的一种特殊形式。我展示了如何在对象上设置任何属性的基本方法。我喜欢Brennan的答案最好,因为它解释了额外的魔法。 - TbWill4321

0

function doSmth() 中的页面与 service 中的页面不在同一命名空间中,即 service.pages

您的 pages[1] 必须在其他地方全局声明。

但是,您正在将 pages 初始化为空(但存在)数组:pages: []

var service = {
    pages: [],
    doSmth: doSmth
};

doSmth();

function doSmth() {
    pages[1] = "abc";
    pages[5] = "def";
}

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