像这样声明数组的真正区别是什么:
var myArray = new Array();
和
var myArray = [];
[]
令牌:ARRAY_INIT
; new Array
令牌:NEW, IDENTIFIER
; new Array()
个令牌:NEW, IDENTIFIER, CALL
有区别,但在该示例中没有区别。
使用更详细的方法: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
进行计算变得困难。
使用隐式数组和数组构造函数创建数组之间的区别是微妙但重要的。
当您使用创建数组时
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(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
,仅此而已,这意味着没有任何 真正的元素 strong> 在这个新创建的数组中。
函数 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]
。
undefined
。
new Array(2)
的等价物应该是 [,,]
,而不是 [undefined, undefined]
,不是吗?
奇怪的是,new Array(size)
在 Chrome 中几乎比 []
快 2 倍,在 FF 和 IE 中几乎相同(通过创建和填充数组来衡量)。仅当您知道数组的大致大小时才重要。如果您添加的项目多于您给定的长度,则性能提升将丢失。
更准确地说:Array(
是一个不分配内存的快速常数时间操作,而 []
是一个设置类型和值的线性时间操作。
new Array(length)
on 0 <= size <= ~1000, on size > ~1000 胜 []
如需更多信息,the following page 说明了您从不需要使用 new Array()
的原因
你永远不需要在 JavaScript 中使用 new Object()。请改用对象文字 {}。同样,不要使用 new Array(),而是使用数组字面量 []。 JavaScript 中的数组与 Java 中的数组完全不同,使用类似 Java 的语法会让您感到困惑。不要使用新数字、新字符串或新布尔值。这些形式产生不必要的对象包装。只需使用简单的文字代替。
另请查看评论 - new Array(length)
表单没有任何用处(至少在今天的 JavaScript 实现中)。
为了更好地理解 []
和 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 控制台。
Array(3)
或 new Array(3)
与 [3]
不同。
第一个是默认的对象构造函数调用。如果需要,您可以使用它的参数。
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 = [5]
但不使用构造函数,因为 var array = Array(5)
会生成一个包含 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() 函数,然后它将我们的“Pushed”值存储在它的“Value”属性中,当我们警告 test2 时也会发生同样的情况,它会返回数组对象的“Value”属性。
因此,当我们检查 test1 是否等于 test2 时,它们当然永远不会返回 true,一个是函数,另一个是变量(具有数组类型),即使它们具有相同的值!
为了确定这一点,请尝试第 4 个警报,并添加 .value;它会返回真。在这种情况下,我们告诉 JS “不管容器的类型,无论是函数还是变量,请比较每个容器中存储的值,并告诉我们你看到了什么!”这正是发生的事情。
我希望我清楚地表达了背后的想法,并为我糟糕的英语感到抱歉。
[]
和 new Array()
相同; .value
在这两种情况下都是 undefined
,比较它们总是错误的。
array.value
这样的东西。 typeof []
和 typeof new Array()
都返回 object
。这就是为什么有一个名为 Array.isArray
的函数的原因之一
初始化没有任何长度的数组时没有区别。所以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
这不仅仅是表面上看到的。大多数其他答案都是正确的,但也..
新数组(n)
允许引擎为 n 个元素重新分配空间
针对阵列创建进行了优化
创建的数组被标记为稀疏,它的数组操作性能最低,这是因为每个索引访问都必须检查边界,查看值是否存在并遍历原型链
如果数组被标记为稀疏,则无法返回(至少在 V8 中),它在其生命周期内总是会变慢,即使您在 1 毫秒或 2 小时后用内容(打包数组)填充它,也没关系
[1, 2, 3] || []
创建的数组被标记为打包(除非您使用 delete 或 [1,,3] 语法)
针对数组操作进行了优化(用于 ..、forEach、map 等)
随着阵列的增长,引擎需要重新分配空间
对于较旧的浏览器版本/浏览器,情况可能并非如此。
第一个是默认的对象构造函数调用。主要用于动态值。
var array = new Array(length); //initialize with default length
创建静态值时使用第二个数组
var array = [red, green, blue, yellow, white]; // this array will contain values.
使用方式的区别
var arr = new Array(size);
或者
arr = [];
arr.length = size;
正如在这个问题中讨论得足够多。
我想添加速度问题 - 当前最快的方式,在 google chrome
上是第二个。
但请注意,这些事情往往会随着更新而发生很大变化。此外,不同浏览器之间的运行时间也会有所不同。
例如 - 我提到的第二个选项在 chrome
上以 200 万 [ops/second] 的速度运行,但如果您在 mozilla dev.
上尝试它,您将获得 2300 万的惊人的更高速率。
无论如何,我建议您每隔一段时间在不同的浏览器(和机器)上使用站点 as such 进行检查
据我所知,你可以找到像 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 的不同实例。所以这解释了为什么 [] != []
:)
没有什么大的区别,它们基本上做同样的事情,但以不同的方式做,但请继续阅读,看看 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)
,这也是不推荐的方式。
new Array(40).fill(123)
有用
我使用 [] 导致了一种奇怪的行为。
我们有模型“类”,其中字段初始化为某个值。例如:
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)
嗯,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()
有足够的解释 :)
我在使用 Promise 时发现了不同之处。在使用承诺数组(比如 arr,初始化为 arr=[])时,在 Promise.all(arr) 中出现错误。而当声明为 arr = Array() 时,没有出现编译问题。希望这可以帮助。
我发现这两种结构之间的一个区别让我很难受。
假设我有:
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()
。
var property1static=[];
function MyClass(){ this.property1=property1static; this.property2=new Array(); };
var MyObject2 = MyObject1;
吗?
使用 Array 构造函数创建一个具有所需长度的新数组,并使用未定义的索引填充每个索引,分配给变量的数组将创建您为其提供信息的索引。