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

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

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

1
var myArray = new Array();

1
var myArray = [];


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

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

;


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

当使用

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(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]


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

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


有关更多信息,下面的页面描述了为什么不需要使用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实现中)。


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


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

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.


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

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"不管容器的类型是函数还是变量,请比较存储在每个容器中的值,并告诉我们您看到了什么!"事情就是这样。

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


没有什么大的区别,他们基本上做相同的事情,但是以不同的方式做,但是继续阅读,看看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()


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