声明JavaScript数组时,“ Array()”和“ []”之间有什么区别?


Answers:


951

有所不同,但在该示例中没有区别。

使用更冗长的方法:new Array()在参数中确实有一个额外的选择:如果将数字传递给构造函数,则将得到一个具有该长度的数组:

x = new Array(5);
alert(x.length); // 5

为了说明创建数组的不同方法:

var a = [],            // these are the same
    b = new Array(),   // a and b are arrays with length 0

    c = ['foo', 'bar'],           // these are the same
    d = new Array('foo', 'bar'),  // c and d are arrays with 2 strings

    // these are different:
    e = [3]             // e.length == 1, e[0] == 3
    f = new Array(3),   // f.length == 3, f[0] == undefined

;

另一个区别是,使用时,new Array()您可以设置数组的大小,这会影响堆栈的大小。如果您遇到堆栈溢出(Array.push与Array.unshift的性能)(当数组的大小超过堆栈的大小并必须重新创建它时会发生这种情况),这将很有用。因此,根据实际情况,使用时实际上可以提高性能,new Array()因为可以防止溢出的发生。

该答案所指出的,new Array(5)实际上不会将五个undefined项目添加到数组中。它只是增加了五个项目的空间。请注意,使用Array这种方式很难依靠它来array.length进行计算。


66
这有点不对。new Array()和[]之间有一个非常重要的区别,我将在答案中进行详细说明。
coderjoe

30
但是,正如您在回答中所指出的那样,仅当您完全疯狂并覆盖Array函数时,这才有所不同。
尼克

19
好吧,重要的是使用new运算符会使解释器采取各种额外的步骤进入全局范围,查找构造函数,调用构造函数并分配结果...在大多数情况下,这将是一个运行时数组。您可以仅使用[]来避免寻找全局构造函数的开销。它可能看起来很小,但是当您在应用中追求近乎实时的性能时,它可能会有所作为。
coderjoe


4
是的,但是在我添加分号或换行符的大多数地方,您也不需要分号或换行符。这是关于一致性和易读性。恕我直言
尼克

774

使用隐式数组创建数组与数组构造函数之间的区别微妙但重要。

当您使用创建数组时

var a = [];

您要告诉解释器创建一个新的运行时数组。完全不需要额外的处理。做完了

如果您使用:

var a = new Array();

您在告诉解释器,我想调用构造函数“ Array”并生成一个对象。然后,它在您的执行上下文中进行查找,以找到要调用的构造函数,并对其进行调用,以创建您的数组。

您可能会认为“嗯,这根本不重要。它们是相同的!”。不幸的是,您不能保证。

请看以下示例:

function Array() {
    this.is = 'SPARTA';
}

var a = new Array();
var b = [];

alert(a.is);  // => 'SPARTA'
alert(b.is);  // => undefined
a.push('Woa'); // => TypeError: a.push is not a function
b.push('Woa'); // => 1 (OK)

在上面的示例中,第一个呼叫将按您的预期提醒“ SPARTA”。第二个不会。您最终将看到未定义。您还将注意到,b包含所有本机Array对象函数,例如push,而其他则不。

虽然你可能希望这样的事情发生,它只是说明了一个事实[]是不一样的new Array()

[]如果您知道只需要一个数组,最好使用它。我也不建议重新定义数组...


156
好吧,我想知道。什么样的人会覆盖数组类,我不知道...
nickf

159
你是绝对正确的。只有疯子才会覆盖数组类。现在花点时间,考虑使用new Array()进行的所有额外工作,使解释器能够支持这些疯子。我只是避免与[]一起使用。
coderjoe

51
JavaScript可能造成的全球污染的一个很好的例子。
David Snabel-Caunt

8
值得注意的是,新的Array(size)比使用[]表示法的其他可能方法快。资料来源:jsperf.com/create-an-array-of-initial-size/2
Marco Luglio 2013年

9
不幸的是,测试准备不当。它正在测试数组的初始化,并先进行数组初始化,然后再进行数组访问。没有任何控件可以证明浏览器实际上已经在预先分配内存(规范并未说明它们必须这样做)。如果我们可以假定数组访问是恒定的,并且在两个示例中大部分时间都将花费在分配内存上,那么如果要实例化数百万个数组,则[]可能更可取。 jsperf.com/array-instanciation
coderjoe 2013年

95

有一个重要的区别,就是尚未提及任何答案。

由此:

new Array(2).length           // 2
new Array(2)[0] === undefined // true
new Array(2)[1] === undefined // true

您可能会认为new Array(2)等于[undefined, undefined]但并非如此!

让我们尝试map()

[undefined, undefined].map(e => 1)  // [1, 1]
new Array(2).map(e => 1)            // "(2) [undefined × 2]" in Chrome

看到?语义完全不同!那为什么呢?

根据ES6 Spec 22.1.1.2,其工作Array(len)只是创建一个属性length设置为参数的新数组,仅len此而已,这意味着新创建的数组中没有任何实际元素

功能map(),根据符合规范22.1.3.15会先检查HasProperty,然后调用回调,但事实证明:

new Array(2).hasOwnProperty(0) // false
[undefined, undefined].hasOwnProperty(0) // true

这就是为什么您不能期望任何迭代函数在从创建的数组上照常工作的原因new Array(len)

BTW,Safari和Firefox在这种情况下具有更好的“打印”效果:

// Safari
new Array(2)             // [](2)
new Array(2).map(e => 1) // [](2) 
[undefined, undefined]   // [undefined, undefined] (2) 

// Firefox
new Array(2)             // Array [ <2 empty slots> ]
new Array(2).map(e => 1) // Array [ <2 empty slots> ]
[undefined, undefined]   // Array [ undefined, undefined ]

我已经向Chromium提交了一个问题,并要求他们解决此令人困惑的打印问题:https : //bugs.chromium.org/p/chromium/issues/detail?id=732021

更新:它已经修复。Chrome现在打印为:

new Array(2)             // (2) [empty × 2]

22
唯一的答案是您的
胜者

这是有道理的,我只是碰到了一个其他的构造,而我找不到针对[...Array(2)]该构造的引用:[undefined, undefined]从结果的角度来看,这等效。
罗伯托·安德拉德

看来我以前的评论的答案是“传播算子”:javascript.info/rest-parameters-spread-operator
罗伯托·安德拉德

@RobertoAndrade之所以有意义,是因为散布运算符将需要读取条目,以便它可以应用此类复制并undefined像往常一样读取此类空槽返回。
Hux

51

奇怪的是,new Array(size)它几乎比[]Chrome 快2倍,而FF和IE 差不多(通过创建和填充数组来衡量)。仅当您知道数组的近似大小时才重要。如果添加的项目多于给定的长度,则会失去性能提升。

更准确地说:Array(是一种不分配内存的快速恒定时间操作,而wheras []是一种设置类型和值的线性时间操作。


3
我已经在Node.js中进行了很多测试:当您需要在数组中放置一些项目时,new Array(length)在0 <=大小<= []
〜1000


40

有关更多信息,以下页面描述了为什么您永远不需要使用new Array()

您无需new Object()在JavaScript中使用。请改用对象文字{} 。同样,请勿使用new Array(),而应使用数组文字[] 。JavaScript中的数组不能像Java中的数组那样工作,使用类似Java的语法会使您感到困惑。

不要使用new Numbernew Stringnew Boolean。这些形式产生不必要的对象包装。只需使用简单的文字即可。

还要检查注释- new Array(length)表单没有任何用处(至少在当今的JavaScript实现中)。


3
克罗克福德也说使用[]而不是新的Array()。不幸的是,他没有在链接的文章中说出原因。我认为这只是空间和速度的问题。javascript.crockford.com/code.html
Nosredna,2009年

4
Crockford不喜欢使用“ new”关键字在Javascript中创建对象的新实例。在演讲中,他表示自己相信这样做会造成歧义,并且与Javascript的原型样式继承不太吻合。他专门指的是用户创建的对象构造函数,但是基于这种信念,很容易理解为什么他建议您不要在有其他语法的情况下也不要将其与内置函数一起使用。
艾伦·斯托姆

@Alan Storm:至少对于Number,String和Boolean,他说“这些形式会产生不必要的对象包装”,但我想这不适用于Array。
BarelyFitz,2009年

10

为了更好地理解[]new Array()

> []
  []
> new Array()
  []
> [] == []
  false
> [] === []
  false
> new Array() == new Array()
  false
> new Array() === new Array()
  false
> typeof ([])
  "object"
> typeof (new Array())
  "object"
> [] === new Array()
  false
> [] == new Array()
  false

以上结果来自Windows 7上的Google Chrome控制台。


4
但是为什么[] == []或[] === []假?
阿努

5
“仅当操作数引用相同的对象时,比较对象的表达式才为真。” (来源:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
srph 2015年

此答案摘录了一些示例,以暗示这两个构造是相同的。此页面上的其他帖子指出了差异,例如Array(3)new Array(3)与不一致[3]
ggorlen19年

8

第一个是默认的对象构造函数调用。您可以根据需要使用其参数。

var array = new Array(5); //initialize with default length 5

第二个使您能够创建非空数组:

var array = [1, 2, 3]; // this array will contain numbers 1, 2, 3.

1
您可以使用冗长的构造函数执行相同的操作:var array = new Array(1,2,3);
尼克

因此,我想您可以var array = [5]使用方括号来执行操作,但不能使用构造函数来var array = Array(5)创建5个元素的空数组。
2009年

cdmckay-这是不正确的。var a = [5]将是一个包含单个项目的数组-数字5。
BarelyFitz

2
@BarelyFitz:我就是这么说的。在Bogdans的回答中,他说不能使用构造函数调用来初始化数组,但是他错了。我的评论只是为了澄清您不能使用构造函数调用来初始化单个元素的数组。
cdmckay,2009年

1
@cdmckay:对不起,我误解了您的评论。需要说明的是:new Array(arg)-如果arg为数字,则创建一个长度为arg的空数组;new Array(arg1,arg2)-创建一个新数组并初始化数组元素。因此,如果要使用一个数字元素(如[5])创建一个数组,则不能使用new Array(5)来实现。但是实际上您永远不应该使用new Array(),所以这是一个有争议的问题。
BarelyFitz

5

我可以从基于Fredrik的好例子的示例开始,以更具体的方式进行解释。

var test1 = [];
test1.push("value");
test1.push("value2");

var test2 = new Array();
test2.push("value");
test2.push("value2");

alert(test1);
alert(test2);
alert(test1 == test2);
alert(test1.value == test2.value);

我刚刚向数组添加了另一个值,并发出了四个警报:第一个和第二个是给我们存储在每个数组中的值,以确保这些值。他们将返回相同的!现在尝试第三个,它返回false,这是因为

JS将test1视为具有数组数据类型的VARIABLE,并将test2视为具有数组功能OBJECT,这里几乎没有什么区别。

第一个区别是,当我们调用test1时,它会不加考虑地调用变量,它只是返回存储在此变量中的值,而不管其数据类型!但是,当我们调用test2时,它将调用Array()函数,然后将其“推入”值存储在其“ Value”属性中,并且当我们警告test2时,也会发生同样的情况,它返回数组对象的“ Value”属性。

因此,当我们检查test1是否等于test2时,它们将永远不会返回true,一个是函数,另一个是变量(具有数组类型),即使它们的值相同!

为确保这一点,请尝试添加了.value的第四个警报。它将返回true。在这种情况下,我们告诉JS“不管容器的类型是功能还是变量,请比较每个容器中存储的值,然后告诉我们您所看到的!” 正是这样。

我希望我清楚地说出了这个主意,并为我的英语不好对不起。


19
如此荒唐而彻底的废话已被投票令人惊讶。不管您如何制作它们,数组之间的比较都是错误的,因为它比较对象标识并且它们是不同的对象。数组没有value属性。[]并且new Array()是相同的;.valueundefined在两种情况下,并比较他们将永远是假的。
slikts

同意,这个答案没有任何意义,什么也没有显示。没有这样的事情array.value。两者typeof []typeof new Array()回报object。这就是为什么有一个叫做Array.isArray
gman

4

初始化没有任何长度的数组时没有任何区别。所以var a = []var b = new Array()一样。

但是,如果初始化长度为like的数组var b = new Array(1);,则会将数组对象的长度设置为1。因此,它等效于 var b = []; b.length=1;

每当您执行array_object.push时,这都会成问题,它会在最后一个元素之后添加项目并增加长度。

var b = new Array(1);
b.push("hello world");
console.log(b.length); // print 2

var v = [];
a.push("hello world");
console.log(b.length); // print 1

3

第一个是默认的对象构造函数调用,主要用于动态值。

var array = new Array(length); //initialize with default length

创建静态值时使用第二个数组

var array = [red, green, blue, yellow, white]; // this array will contain values.

3

两者之间没有太大区别,它们基本上是做相同的事情,但是以不同的方式来做,但是请继续阅读W3C的以下语句:

var cars = ["Saab", "Volvo","BMW"];

var cars = new Array("Saab", "Volvo", "BMW");

上面的两个示例完全相同。无需使用新的Array()。
为了简单起见,提高可读性和执行速度,请使用第一个(数组文字方法)。

但是同时,使用new Array语法创建新数组被认为是不好的做法:

避免使用新的Array()

无需使用JavaScript的内置数组构造函数new Array()。
使用[]代替。
这两个不同的语句都创建了一个新的名为点的空数组:

var points = new Array();         // Bad
var points = [];                  // Good 

这两个不同的语句都创建一个包含6个数字的新数组:

var points = new Array(40, 100, 1, 5, 25, 10); // Bad    
var points = [40, 100, 1, 5, 25, 10];          // Good

新的关键字唯一的代码复杂化。它还可能产生一些意外的结果:

var points = new Array(40, 100);  // Creates an array with two elements (40 and 100)

如果我删除其中一个元素怎么办?

var points = new Array(40);       // Creates an array with 40 undefined elements !!!!!

因此,基本上不被视为最佳实践,那里也有一个细微的差别,您可以new Array(length)像这样传递长度,这也不是推荐的方法。


嗨,Alireza,这些是从某处复制粘贴吗?请添加一个链接到复制文本的页面。有关详情,请参见此帮助中心页面。谢谢。
庞(Pang)

适用于new Array(40).fill(123)
gman19年

2

使用的区别

var arr = new Array(size);

要么

arr = [];
arr.length = size;

正如在这个问题上已经足够讨论的。

我想补充一下速度问题- 当前最快的方法google chrome是第二个。

但是请注意,这些事情会随着更新而发生很大变化。不同浏览器的运行时间也不同。

例如-我提到的第二个选项在上以200万[ops / second]的速度运行chrome,但是如果您尝试在mozilla dev.获得2300万的惊人的高速率。

无论如何,我建议你在一段时间检查出来,每一次,在不同的浏览器(和机器),利用网站这样


2

正如我所知道的性差异u能找到切片(或阵列的其他funcitons)像编码1。而代码2显示ü 阵列和他的情况下,

代码1:

[].slice; // find slice here
var arr = new Array();
arr.slice // find slice here
Array.prototype.slice // find slice here

代码2:

[].__proto__ == Array.prototype; // true
var arr = new Array();
arr.__proto__ == Array.prototype; // true

结论:

就像你看到的[]new Array()创建了一个新的Array实例。Array.prototype

它们只是Array。的不同实例,所以这解释了为什么 [] != []

:)


2

我使用[]引起了奇怪的行为。

我们有模型“类”,其字段已初始化为某个值。例如:

require([
  "dojo/_base/declare",
  "dijit/_WidgetBase",
], function(declare, parser, ready, _WidgetBase){

   declare("MyWidget", [_WidgetBase], {
     field1: [],
     field2: "",
     function1: function(),
     function2: function()
   });    
});

我发现,使用字段初始化时[],所有Model对象都将共享它。对一个进行更改会影响所有其他更改。

使用初始化它们不会发生new Array()。与Objects的初始化相同({}与new相同Object()

TBH我不确定我们使用的框架是否有问题(Dojo


2

除了眼神之外,这还不止于此。大多数其他答案也是正确的,但是 ..

new Array(n)

  • 允许引擎为n元素重新分配空间
  • 针对数组创建进行了优化
  • 创建的数组被标记为稀疏,其执行的数组性能最低,这是因为每次索引访问都必须检查边界,查看值是否存在并遍历原型链
  • 如果将数组标记为稀疏,则没有回退的方式(至少在V8中如此),即使在1ms或2小时后填充了内容(压缩数组),它在其生命周期中也总是会变慢,这没关系

[1, 2, 3] || []

  • 创建的数组标记为已打包(除非您使用delete[1,,3]语法)
  • 针对阵列操作进行了优化(for ..forEachmap等)
  • 引擎需要随着数组的增长重新分配空间

可能是在旧的版本的浏览器/浏览器的情况。


-2

我发现这两种结构之间的一个区别让我很难受。

假设我有:

function MyClass(){
  this.property1=[];
  this.property2=new Array();
};
var MyObject1=new MyClass();
var MyObject2=new MyClass();

在现实生活中,如果我这样做:

MyObject1.property1.push('a');
MyObject1.property2.push('b');
MyObject2.property1.push('c');
MyObject2.property2.push('d');

我最终得到的是:

MyObject1.property1=['a','c']
MyObject1.property2=['b']
MyObject2.property1=['a','c']
MyObject2.property2=['d']

我不知道语言规范所说的应该发生什么,但是如果我希望两个对象在我的对象中具有唯一的属性数组,则必须使用new Array()


此JSFiddle显示了输出与数组文字[]new Array()构造函数所期望的结果,导致每个属性每个数组有一项。您必须在代码中进行其他操作,才能得到上面显示的结果。
gfullam 2015年

Bucky,在任何浏览器中我都不会发生。要获得该行为,您必须执行以下操作: var property1static=[]; function MyClass(){ this.property1=property1static; this.property2=new Array(); };
Dave Burton

-3

使用Array构造函数将创建一个具有所需长度的新数组,并使用未定义填充每个索引,将一个数组分配给一个变量将创建您为其提供信息的索引。


1
不,不填充数组,里面没有索引/键。例如,.forEach将不起作用。
CFrei
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.