921

像这样声明数组的真正区别是什么:

var myArray = new Array();

var myArray = [];
4

18 回答 18

1038

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

使用更详细的方法: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

于 2009-05-31T11:25:01.970 回答
799

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

当您使用创建数组时

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().

[]如果你知道你只想要一个数组,最好只使用它。我也不建议四处走动并重新定义数组...

于 2009-08-13T19:00:16.127 回答
122

有一个重要的区别尚未提及。

由此:

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中没有任何真正的元素。

Function map(),根据规范 22.1.3.15 将首先检查HasProperty然后调用回调,但事实证明:

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

这就是为什么您不能期望任何迭代函数在从new Array(len).

顺便说一句,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]
于 2017-06-10T09:26:13.127 回答
55

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

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

于 2010-06-28T12:35:02.810 回答
44

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

你永远不需要new Object()在 JavaScript 中使用。请改用对象文字{} 。同样,不要使用new Array(),而是使用数组文字[] 。JavaScript 中的数组与 Java 中的数组完全不同,使用类似 Java 的语法会让您感到困惑。

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

另请查看评论 - 该new Array(length)表单没有任何有用的目的(至少在今天的 JavaScript 实现中)。

于 2009-05-31T16:29:12.540 回答
9

为了更好地理解[]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 控制台。

于 2012-07-27T22:56:40.750 回答
8

第一个是默认的对象构造函数调用。如果需要,您可以使用它的参数。

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

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

var array = [1, 2, 3]; // this array will contain numbers 1, 2, 3.
于 2009-05-31T11:53:26.343 回答
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 ,数据类型为 array,将test2视为OBJECT ,具有 array 的功能,此处略有不同。

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

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

为了确定这一点,请尝试第 4 个警报,并添加 .value;它会返回真。在这种情况下,我们告诉 JS “不管容器的类型,无论是函数还是变量,请比较每个容器中存储的值,并告诉我们你看到了什么!” 这正是发生的事情。

我希望我清楚地表达了背后的想法,并为我糟糕的英语感到抱歉。

于 2013-05-06T16:52:20.330 回答
4

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

但是如果你用长度初始化数组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
于 2019-03-13T18:59:23.507 回答
3

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

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

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

var array = [red, green, blue, yellow, white]; // this array will contain values.
于 2016-08-31T17:06:07.527 回答
3

这不仅仅是表面上看到的。大多数其他答案都是正确的,也..

new Array(n)

  • 允许引擎为n元素重新分配空间
  • 针对阵列创建进行了优化
  • 创建的数组被标记为稀疏,它的数组操作性能最低,这是因为每个索引访问都必须检查边界,查看值是否存在并遍历原型链
  • 如果数组被标记为稀疏,则无法返回(至少在 V8 中),它在其生命周期内总是会变慢,即使您在 1 毫秒或 2 小时后用内容(打包数组)填充它,也没关系

[1, 2, 3] || []

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

对于较旧的浏览器版本/浏览器,情况可能并非如此。

于 2019-12-10T15:49:58.467 回答
3

好吧,与某些功能的var x = new Array()不同之var x = []处不同,我将仅解释其中最有用的两个(在我看来)。

在我开始解释差异之前,我将首先设定一个基础;当我们使用x = []定义一个数据类型为 Array 的新变量时,它继承了属于数组原型的所有方法,这与扩展类非常相似(但不完全是)。但是,当我们使用x = new Array()它时,它会初始化分配给变量的数组原型的克隆x

现在让我们看看有什么区别

第一个区别是使用new Array(x)wherex是一个整数,初始化一个x未定义值的数组,例如new Array(16)将初始化一个包含 16 个项的数组,所有这些项都是未定义的。当您异步填充预定义长度的数组时,这非常有用。例如(再次:))假设您正在获得 100 个竞争对手的结果,并且您从远程系统或数据库异步接收它们,那么您需要在收到后根据排名在数组中分配它们每个结果。在这种非常罕见的情况下,您将执行类似的操作myArray[result.rank - 1] = result.name,因此排名 1 将设置为索引 0,依此类推。

第二个区别是使用new Array()你已经知道的,实例化一个全新的数组原型克隆并将它分配给你的变量,这允许你做一些魔法(不推荐顺便说一句)。这个神奇之处在于您可以覆盖遗留数组方法的特定方法。因此,例如,您可以将Array.push方法设置为将新值推送到数组的开头而不是结尾,您还可以将新方法(这更好)添加到 Array Prototype 的这个特定克隆中。这将允许您使用自己添加的方法在整个项目中定义更复杂的数组类型并将其用作类。

最后一件事,如果您来自极少数(我真正喜欢的)关心应用程序的处理开销和内存消耗的人,那么您永远new Array()不会不顾一切地使用它:)。

我希望这已经对野兽进行了足够的解释new Array():)

于 2020-06-14T15:14:08.907 回答
2

使用方式的区别

var arr = new Array(size);

或者

arr = [];
arr.length = size;

正如在这个问题中讨论得足够多。

我想补充一下速度问题——目前最快的方式google chrome是第二种。

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

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

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

于 2016-03-06T09:23:59.890 回答
2

据我所知,你可以找到像code1这样的切片(或Array的其他功能)。code2显示你的Array和他的实例

代码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 的不同实例。所以这解释了原因 [] != []

:)

于 2016-12-27T06:14:40.560 回答
2

没有什么大的区别,它们基本上做同样的事情,但以不同的方式做,但请继续阅读,看看 W3C 的这个声明:

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

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

上面的两个例子完全一样。无需使用 new Array()。
为了简单、可读性和执行速度,使用第一个(数组文字方法)。

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

避免使用新的 Array()

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

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

new关键字只会使代码复杂化。它还会产生一些意想不到的结果:

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)像这样传递长度,这也是不推荐的方式。

于 2017-05-26T16:23:26.820 回答
2

我使用 [] 导致了一种奇怪的行为。

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

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

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

我发现当字段被初始化时,[]它会被所有模型对象共享。对其中一项进行更改会影响所有其他项。

用 初始化它们不会发生这种情况new Array()。对象的初始化相同({}vs new Object()

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

于 2017-09-19T15:26:46.293 回答
-4

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

假设我有:

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().

于 2015-09-24T00:08:47.830 回答
-4

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

于 2015-11-19T16:20:37.193 回答