ChatGPT解决这个技术问题 Extra ChatGPT

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

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

var myArray = new Array();

var myArray = [];
[] 令牌:ARRAY_INITnew Array 令牌:NEW, IDENTIFIERnew Array() 个令牌:NEW, IDENTIFIER, CALL

A
Adam Gerthel

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

使用更详细的方法: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() 时,您可以设置数组的大小,这会影响堆栈大小。如果您遇到堆栈溢出 (Performance of Array.push vs Array.unshift),这是很有用的,当数组的大小超过堆栈的大小时会发生这种情况,并且必须重新创建它。所以实际上,根据用例,使用 new Array() 可以提高性能,因为您可以防止发生溢出。

正如 this answer 中所指出的,new Array(5) 实际上不会将五个 undefined 项添加到数组中。它只是为五个项目增加了空间。请注意,以这种方式使用 Array 会使依赖 array.length 进行计算变得困难。


这有点不对。 new Array() 和 [] 之间有一个非常重要的区别,我将在我的回答中详细说明。
但正如您在回答中指出的那样,只有当您完全疯了并覆盖 Array 函数时才会有所不同..?
重要的是,使用 new 运算符会导致解释器采取各种额外的步骤进入全局范围,查找构造函数,调用构造函数并分配结果......在大多数情况下,这将是一个运行时数组。您可以通过使用 [] 来避免查找全局构造函数的开销。它可能看起来很小,但是当您在应用程序中追求近乎实时的性能时,它会有所作为。
存在巨大的性能差异:jsperf.com/create-an-array-of-initial-size/2
没错,但在我添加分号或换行符的大多数地方,您也不需要分号或换行符。这是关于一致性和易读性。你知道,恕我直言。
C
Community

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

当您使用创建数组时

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() 不同的事实。

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


好吧,很高兴知道我想。什么样的人会覆盖数组类,我不知道......
你是绝对正确的。只有疯子才会覆盖数组类。现在花点时间考虑一下使用 new Array() 所做的所有额外工作使解释器能够支持这些疯子。我只是和[]一起避免了这一切。
JavaScript 可能造成的全球污染的一个很好的例子。
值得注意的是,新的 Array(size) 比使用 [] 表示法的其他可能方法更快。来源:jsperf.com/create-an-array-of-initial-size/2
不幸的是,该测试准备不当。它正在测试一个数组的初始化,其中包含数组的初始化,然后是数组访问。无法控制来证明浏览器实际上是在预先分配内存(规范并没有说它们必须这样做)。如果我们可以假设数组访问是恒定的,并且在这两个示例中大部分时间都将用于分配内存,那么如果您要实例化数百万个数组,则 [] 可能更可取。 jsperf.com/array-instanciation
H
Hux

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

由此:

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) 创建的数组上照常工作。

顺便说一句,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]

这是有道理的,我只是碰到了一个不同的结构,我找不到以下的文档引用:[...Array(2)] 从结果的角度来看,它等同于 [undefined, undefined]
看起来我之前评论的答案是“扩展运算符”:javascript.info/rest-parameters-spread-operator
@RobertoAndrade 这很有意义,因为扩展运算符将需要读取条目,以便它可以应用这样的复制......并像往常一样读取这样的空槽返回 undefined
new Array(2) 的等价物应该是 [,,],而不是 [undefined, undefined],不是吗?
E
Eric Leschinski

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

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


我在 Node.js 中对其进行了很多测试:当您需要将一些项目放入数组中时,new Array(length) on 0 <= size <= ~1000, on size > ~1000 胜 []
A
Aliaksandr Sushkevich

如需更多信息,the following page 说明了您从不需要使用 new Array() 的原因

你永远不需要在 JavaScript 中使用 new Object()。请改用对象文字 {}。同样,不要使用 new Array(),而是使用数组字面量 []。 JavaScript 中的数组与 Java 中的数组完全不同,使用类似 Java 的语法会让您感到困惑。不要使用新数字、新字符串或新布尔值。这些形式产生不必要的对象包装。只需使用简单的文字代替。

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


Crockford 也说使用 [] 而不是 new Array()。不幸的是,他没有在链接的文章中说明原因。我认为这只是空间和速度的问题。 javascript.crockford.com/code.html
Crockford 不喜欢使用“new”关键字在 Javascript 中创建对象的新实例。在讲座中,他表示他认为它会产生歧义,并且不适合 Javascript 的原型样式继承。他特别指的是用户创建的对象构造函数,但鉴于这种信念,很容易理解为什么他建议您不要将它与内置函数一起使用,因为有替代语法。
@Alan Storm:至少对于 Number、String 和 Boolean,他说“这些形式会产生不必要的对象包装”,但我想这不适用于 Array。
P
Peter Lee

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


但为什么 [] == [] 或 [] === [] false ?
“仅当操作数引用相同的对象时,比较对象的表达式才为真。” (来源:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
这个答案樱桃挑选了一些例子来暗示这两个结构是相同的。此页面上的其他帖子指出了差异,例如 Array(3)new Array(3)[3] 不同。
B
Bogdan Gusiev

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

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

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

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。
@BarelyFitz:我就是这么说的。在 Bogdans 的回答中,他说构造函数调用不能用于初始化数组,但他错了。我的评论只是为了澄清您不能使用构造函数调用来初始化单个元素的数组。
@cdmckay:对不起,我误解了你的评论。澄清一下: new Array(arg) - 如果 arg 是数字,这将创建一个长度为 arg 的空数组; new Array(arg1, arg2) - 创建一个新数组并初始化数组元素。因此,如果您想创建一个包含一个数字元素的数组,如 [5],则无法使用 new Array(5) 来实现。但实际上你永远不应该使用 new Array() 所以这是一个有争议的问题。
K
Kholio

我可以从这个基于 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() 函数,然后它将我们的“Pushed”值存储在它的“Value”属性中,当我们警告 test2 时也会发生同样的情况,它会返回数组对象的“Value”属性。

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

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

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


令人惊讶的是,如此完整而完全的废话被投票赞成。无论您如何制作数组之间的比较都是错误的,因为它比较对象身份并且它们是不同的对象。数组没有值属性。 []new Array() 相同; .value 在这两种情况下都是 undefined,比较它们总是错误的。
同意,这个答案没有任何意义,也没有显示任何内容。没有 array.value 这样的东西。 typeof []typeof new Array() 都返回 object。这就是为什么有一个名为 Array.isArray 的函数的原因之一
好吧,伙计们,我同意你的看法:)当时我写了一个完整的废话:)。现在我已经为同一个问题添加了正确答案。让我知道你看到了什么。我非常感谢您的意见。
A
Aniruddha

初始化没有任何长度的数组时没有区别。所以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

S
Solo

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

新数组(n)

允许引擎为 n 个元素重新分配空间

针对阵列创建进行了优化

创建的数组被标记为稀疏,它的数组操作性能最低,这是因为每个索引访问都必须检查边界,查看值是否存在并遍历原型链

如果数组被标记为稀疏,则无法返回(至少在 V8 中),它在其生命周期内总是会变慢,即使您在 1 毫秒或 2 小时后用内容(打包数组)填充它,也没关系

[1, 2, 3] || []

创建的数组被标记为打包(除非您使用 delete 或 [1,,3] 语法)

针对数组操作进行了优化(用于 ..、forEach、map 等)

随着阵列的增长,引擎需要重新分配空间

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


m
miken32

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

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

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

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

X
Xavier Egea

使用方式的区别

var arr = new Array(size);

或者

arr = [];
arr.length = size;

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

我想添加速度问题 - 当前最快的方式,在 google chrome 上是第二个。

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

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

无论如何,我建议您每隔一段时间在不同的浏览器(和机器)上使用站点 as such 进行检查


s
sammy

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

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

:)


A
Alireza

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

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

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

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

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

避免使用 new 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),这也是不推荐的方式。


嗨 Alireza,这些是从某个地方复制和粘贴的吗?请添加指向复制文本的页面的链接。有关详细信息,请参阅 this help center page。谢谢你。
new Array(40).fill(123) 有用
a
algiogia

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

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

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

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

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

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

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


K
Kholio

嗯,var x = new Array() 不同于 var x = [] 在某些功能上有所不同 我将解释其中最有用的两个(在我看来)。

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

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

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

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

最后一件事,如果您来自极少数(我真正喜欢的)关心应用程序的处理开销和内存消耗的人,那么您绝不会在不急于使用它的情况下遇到困难new Array() :)。

我希望这对野兽 new Array() 有足够的解释 :)


p
pranav karthik

我在使用 Promise 时发现了不同之处。在使用承诺数组(比如 arr,初始化为 arr=[])时,在 Promise.all(arr) 中出现错误。而当声明为 arr = Array() 时,没有出现编译问题。希望这可以帮助。


B
Bucky

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

假设我有:

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


This JSFiddle 显示输出是您对数组文字 []new Array() 构造函数所期望的输出,导致每个属性每个数组一个项目。您必须在代码中进行其他操作才能得到上面显示的结果。
Bucky,在任何浏览器中都不会发生这种情况。要获得这种行为,您必须执行以下操作:var property1static=[]; function MyClass(){ this.property1=property1static; this.property2=new Array(); };
你确定你没有做var MyObject2 = MyObject1;吗?
T
Timothy Trousdale

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


不,没有填充数组,里面没有索引/键。例如 .forEach 不起作用。