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

What’s the difference between “Array()” and “[]” while declaring a JavaScript array?

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

1
var myArray = new Array();

1
var myArray = [];

  • []令牌:ARRAY_INITnew ArrayNEW, IDENTIFIER标记:标记:NEW, IDENTIFIER, CALLnew Array()


有区别,但在那个例子中没有区别。

使用更详细的方法:new Array()在参数中有一个额外的选项:如果向构造函数传递一个数字,您将得到一个该长度的数组:

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

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

1
2
3
4
5
6
7
8
9
10
11
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()和[]之间有一个非常重要的区别,我将在我的答案中详细说明。
  • 但正如你的答案中所指出的,只有当你完全疯了并且覆盖了数组函数时,情况才会不同。
  • 重要的是,使用这个新的操作符会使解释器采取各种额外的步骤,进入全局范围,查找构造函数,调用构造函数并分配结果…在大多数情况下,它将是一个运行时数组。只需使用[]就可以避免查找全局构造函数的开销。它可能看起来很小,但当你在应用程序中为接近实时的性能而拍摄时,它可能会产生影响。
  • @nickf你使用===可能会让外行感到困惑,特别是那些测试是错误的,因为它们没有比较同一个对象。它们可能无法区分,但它们并不相等。
  • 有一个巨大的性能差异:jspef.com/create-an-array-of-initial-size/2
  • 是的,但在我添加分号或换行符的大多数地方,您也不需要分号或换行符。这是关于一致性和易读性。你知道吗?


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

当使用

1
var a = [];

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

如果使用:

1
var a = new Array();

您要告诉解释器,我想调用构造函数"Array"并生成一个对象。然后,它通过执行上下文查找要调用的构造函数,并调用它,从而创建数组。

你可能会想,"好吧,这一点都不重要。他们是一样的!"很遗憾,你不能保证。

举个例子:

1
2
3
4
5
6
7
8
9
10
11
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包含所有本机数组对象函数,如push,而另一个则不包含。

虽然您可能希望发生这种情况,但它只是说明了这样一个事实:[]new Array()不同。

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

  • 好吧,我想很高兴知道。什么样的人会覆盖数组类,我不知道…
  • 你说得对。只有疯子才会覆盖数组类。现在花点时间考虑一下使用new array()使解释器做的所有额外工作,以支持这些疯子。我只是和[]一起避免这一切。
  • 很好的例子说明了Javascript可能带来的全球污染。
  • 值得注意的是,新数组(大小)比使用[]表示法的其他可能方法更快。来源:jspef.com/create-an-array-of-initial-size/2
  • 不幸的是,测试准备不当。它正在测试数组的初始化,先初始化数组,然后访问数组。没有控制来证明浏览器实际上是预先分配了内存(规范没有规定必须这样做)。如果我们可以假设数组访问是恒定的,并且大部分时间将花费在两个示例中分配内存,那么如果您要实例化数百万个数组,则最好使用[]。jspef.com/array-安装
  • 不过,扩展数组是很好的,比如创建一个array.map()函数(实际上我在一次采访中必须这样做)。
  • 我不同意。当您的array.map版本和我的array.map版本冲突并具有不同的方法签名时会发生什么?我也不是随便编出来的。我在使用盲目扩展核心对象的库时遇到了这个问题。如果你是唯一一个这样做的人,那可能没问题,但是当你开始使用外部库的时候,你可能会给自己带来很多麻烦。现在,我更喜欢包装对象、外部支持函数或库,它们允许您选择何时扩展核心功能(并确保不要在内部依赖它)。
  • 这可能很有趣。jslinterrors.com/the-array-literal-notation-is-preferrable
  • 这是疯狂XP
  • @coderjoe"只有疯子才会覆盖数组类"是这样的。许多程序员都会做这种疯狂的事情。
  • 斯巴达人是疯子。
  • 您能详细说明这一点吗?(var a=[])您要告诉解释器创建一个新的运行时数组?JS引擎是否调用数组构造函数来创建运行时数组?
  • @hackjutsu我相信解释器的本机数组构造函数是被调用的,任何重写的构造函数都不是。这说明了吗?
  • 我认为这个答案与OP的问题无关。您基本上指出了javascript的一个特性/缺陷,即所有对象都可以被覆盖。是的,当然,但是这个答案不属于关于数组的问题,它属于对javascript对象的讨论:在每个对象上放置这个免责声明只会将fud添加到学习过程中。
  • @皮特,我相信你完全没抓住要点。覆盖数组用作示例,但它不是使用"var a=[]"和"var a=new array();"之间的区别。前者不使用全局定义的构造函数,后者使用全局定义的构造函数。覆盖对象只是作为一个方便的用户可执行的例子来证明这一点。javascript的"特性/缺陷"与此无关。手术问有什么区别,这个问题回答了。一个版本忽略全局定义的对象构造函数,另一个版本则不忽略。
  • 你的回答与问题无关。您声明了自己的函数"array",因此创建了新的本地范围"array",这与javascript内置数组对象无关。所以当调用new array()时,与javascript数组无关。


有一个巨大的差异,没有人提到。

你可能认为new Array(2)相当于[undefined, undefined],因为我们

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

但它不是!

让我们试试map()

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

看到了吗?不一样!但为什么呢?

根据ES6规范22.1.1.2,Array(len)只创建了一个新的数组,length设置为len而不是更多。因此,新数组中没有真正的元素。

根据规范22.1.3.15,函数map()首先检查HasProperty然后调用回调,但结果是:

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

这就是为什么您不能期望任何迭代函数像往常一样工作于从new Array(len)创建的数组。

btw、safari和firefox对此有更好的表达:

1
2
3
4
5
6
7
8
9
// 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 ]

我已经向Chrome提交了一个问题,要求他们修复这个令人困惑的日志:https://bugs.chromium.org/p/chromium/issues/detail?ID=732021

更新:已经修复。Chrome现在登录为

1
new Array(2)             // (2)&nbsp;[empty × 2]

  • 你的答案是唯一真实的
  • 这是正确的答案
  • 这是有道理的,我只是碰到了一个不同的构造,我找不到文档化的参考:从结果的角度来看,[...Array(2)]相当于[undefined, undefined]
  • 我之前评论的答案是"spread operator":javascript.info/rest-parameters-spread-operator


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

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

  • 我在node.js中做了很多测试:当你需要在数组中放入一些项目时,new Array(length)on 0<=size<=~1000,on size-~1000赢得[]
  • 查看stackoverflow.com/questions/7375120/&hellip;


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

You never need to use new Object() in
JavaScript. Use the object literal {}
instead. Similarly, don’t use new Array(),
use the array literal []
instead. Arrays in JavaScript work
nothing like the arrays in Java, and
use of the Java-like syntax will
confuse you.

Do not use new Number, new String, or
new Boolean. These forms produce
unnecessary object wrappers. Just use
simple literals instead.

还可以查看注释-new Array(length)表单没有任何有用的用途(至少在今天的javascript实现中)。

  • Crockford也说要使用[]而不是新数组()。不幸的是,他没有在相关文章中说明原因。我想这只是空间和速度的问题。javascript.crockford.com/code.html
  • Crockford不喜欢使用"new"关键字在javascript中创建对象的新实例。在讲座中,他说,他相信这会造成歧义,不适合JavaScript的原型样式继承。他专门指的是用户创建的对象构造器,但考虑到这一点,很容易理解为什么他建议在有其他语法的情况下,不要将其与内置结构一起使用。
  • @AlanStorm:至少对于数字、字符串和布尔值,他说"这些形式产生了不必要的对象包装器",但我猜这不适用于数组。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
> []
  []
> 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

以上结果来自Windows7上的GoogleChrome控制台。

  • 但为什么[]==[]或[]==[]是假的?
  • "只有当操作数引用同一对象时,表达式比较对象才为真。"(来源:developer.mozilla.org/en-us/docs/web/javascript/reference/&hellip;)


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

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

第二种方法使您能够创建非空数组:

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

  • 您可以使用详细的构造函数做同样的事情:var array=new array(1,2,3);
  • 所以我想你可以用方括号来做var array = [5],但不用构造函数,因为var array = Array(5)可以生成一个由5个元素组成的空数组。
  • cdmckay-那是不正确的。var a=[5]将是一个带有单个项的数组-数字5。
  • @巴里菲茨:我就是这么说的。在Bogdans的回答中,他说构造函数调用不能用于初始化数组,但他错了。我的意见只是澄清,您不能使用构造函数调用初始化单个元素的数组。
  • @对不起,我误解了你的意见。要澄清:new array(arg)-如果arg是数字,则创建长度为arg的空数组;new array(arg1,arg2)-创建新数组并初始化数组元素。因此,如果要使用一个数字元素(如[5])创建数组,则不能使用新数组(5)来创建。但实际上,您不应该使用new array(),所以这是一个无意义的点。
  • 另外,new array("foo")将创建一个带有单个元素的数组,但是,只有当arg不是数字时才能使用。
  • 我认为值得一提的是,[1,2,3,4,5]的速度几乎和new Array(5)的速度一样快,后者只是在准备存储……请参阅jspef.com/array-instationation/2并在投诉前阅读测试用例,下半部分与上半部分测试不做相同的事情,最后三个用例也有值分配。


我可以用更具体的方式来解释,从这个基于弗雷德里克的好例子开始。

1
2
3
4
5
6
7
8
9
10
11
12
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);

我刚刚为数组添加了另一个值,并发出了四个警报:第一个和第二个是给我们每个数组中存储的值,以确定这些值。他们也会回来的!现在试试第三个,它返回错误,那是因为

JS treats test1 as a VARIABLE with a data type of array, and it treats test2 as an OBJECT with the functionality of an array, and
there are few slight differences here.

第一个不同点是,当我们调用test1时,它调用一个变量而不进行思考,它只返回存储在这个变量中的值,而不考虑它的数据类型!但是,当我们调用test2时,它调用array()函数,然后将我们的"pushed"值存储在它的"value"属性中,当我们通知test2时,它也会返回array对象的"value"属性。

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

要确定这一点,请尝试添加.value的第四个警报;它将返回true。在这种情况下,我们告诉JS"不管容器的类型是函数还是变量,请比较存储在每个容器中的值,并告诉我们您看到了什么!"事情就是这样。

我希望我清楚地说出了背后的想法,并为我糟糕的英语道歉。

  • 令人惊讶的是,如此彻底而彻底的胡说八道竟然被投票否决了。无论您如何制作数组,数组之间的比较都将是错误的,因为它比较对象标识和它们是不同的对象。数组没有值属性。[]new Array()是相同的;.value在这两种情况下都是undefined的,比较它们总是错误的。


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

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

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

The two examples above do exactly the same. There is no need to use
new Array(). For simplicity, readability and execution speed, use the
first one (the array literal method).

但同时,使用new Array语法创建新的数组被认为是一种糟糕的做法:

Avoid new Array()

There is no need to use the JavaScript's built-in array constructor
new Array().
Use [] instead.
These two different statements both create a new empty array named
points:

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

These two different statements both create a new array containing 6
numbers:

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

The new keyword only complicates the code. It can also produce some
unexpected results:

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

What if I remove one of the elements?

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

所以基本上不认为是最佳实践,也有一个小的区别,你可以这样把长度传递给new Array(length),这也是不推荐的方法。

  • 嗨,阿里扎,这些是从什么地方复制粘贴的吗?请添加一个指向文本复制来源页面的链接。有关详细信息,请参阅此帮助中心页面。谢谢您。


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

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

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

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

我用[]犯了一个奇怪的行为。

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

1
2
3
4
5
6
7
8
9
10
11
12
require([
 "dojo/_base/declare",
 "dijit/_WidgetBase",
], function(declare, parser, ready, _WidgetBase){

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

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

这不会用new Array()初始化它们。初始化对象({}与新Object()相同)

我不确定我们使用的框架(dojo)是否有问题。


如我所知,差异U可以找到切片(或数组的其他功能),如code1。code2显示U数组及其实例:

代码1:

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

代码2:

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

结论:

如你所见,[]new Array()创建了一个新的数组实例,它们都从Array.prototype获得了原型函数。

它们只是数组的不同实例。[] != []

:)


使用的差异

1
var arr = new Array(size);

1
2
arr = [];
arr.length = size;

在这个问题上讨论得够多了。

我想补充一下速度问题——目前最快的方法,在google chrome上是第二个。

但是请注意,这些事情往往会随着更新而改变很多。另外,不同浏览器的运行时间也不同。

例如,我提到的第二个选项,在chrome上的运行速度是200万次[每秒操作],但是如果你在mozilla dev.上尝试,你会得到2300万次惊人的高速度。

不管怎样,我建议你每隔一段时间在不同的浏览器(和机器)上查看一次,像这样使用站点


初始化没有任何长度的数组时没有区别。因此,var a = []var b = new Array()是相同的。

但是,如果用长度像var b = new Array(1);初始化数组,它会将数组对象的长度设置为1。所以它相当于var b = []; b.length=1;

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

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

VS

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

我发现这两种结构有一个不同之处,那就是咬得我很厉害。

假设我有:

1
2
3
4
5
6
function MyClass(){
  this.property1=[];
  this.property2=new Array();
};
var MyObject1=new MyClass();
var MyObject2=new MyClass();

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

1
2
3
4
MyObject1.property1.push('a');
MyObject1.property2.push('b');
MyObject2.property1.push('c');
MyObject2.property2.push('d');

我最后得出的结论是:

1
2
3
4
MyObject1.property1=['a','c']
MyObject1.property2=['b']
MyObject2.property1=['a','c']
MyObject2.property2=['d']

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

  • 这个jfiddle表明,输出是您对数组文字[]new Array()构造函数的期望,每个属性每个数组产生一个项。您的代码中必须有其他事情发生才能得到上面显示的结果。
  • Bucky,在任何浏览器中都不会发生这种情况。为了达到这种行为,你必须这样做:var property1static=[];function MyClass(){ this.property1=property1static; this.property2=new Array(); };


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

  • 不,数组未填充,内部没有索引/键。例如,foreach不起作用。