JavaScript配列を宣言する際の「Array()」と「[]」の違いは何ですか?


841

このような配列を宣言することの本当の違いは何ですか:

var myArray = new Array();

そして

var myArray = [];

[]トークン:ARRAY_INIT; new Arrayトークン:NEW, IDENTIFIER; new Array()トークン:NEW, IDENTIFIER, CALL
noobninja

回答:


951

違いはありますが、その例では違いはありません。

more verboseメソッドを使用するnew Array()と、パラメーターに1つの追加オプションがあります。コンストラクターに数値を渡すと、その長さの配列が取得されます。

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

;

もう1つの違いは、使用時にnew Array()配列のサイズを設定できるため、スタックサイズに影響することです。これは、配列のサイズがスタックのサイズを超え、再作成する必要があるスタックオーバーフロー(Array.pushとArray.unshiftのパフォーマンス)が発生している場合に役立ちます。したがって、実際には、使用状況によってはnew Array()、オーバーフローの発生を防止できるため、使用時にパフォーマンスが向上する可能性があります。

この回答で指摘されているようにnew Array(5)実際undefinedには配列に5つの項目を追加しません。5つのアイテムのためのスペースを追加するだけです。Arrayこの方法を使用するとarray.length、計算に依存することが難しくなることに注意してください。


66
これは少し間違っています。new Array()と[]の間には1つの非常に重要な違いがあります。
coderjoe 2009

30
しかし、あなたの答えで述べたように、あなたが完全に異常で配列関数を上書きした場合にのみ、それは異なります。
nickf 2009

19
重要なのは、new演算子を使用すると、インタープリターがあらゆる種類の追加手順を実行してグローバルスコープに移動し、コンストラクターを探し、コンストラクターを呼び出して結果を割り当てることです...ランタイム配列。[]を使用するだけで、グローバルコンストラクターを探すオーバーヘッドを回避できます。小さく見えるかもしれませんが、アプリでほぼリアルタイムのパフォーマンスを狙って撮影している場合、違いが生じる可能性があります。
coderjoe 2009

5
パフォーマンスに大きな違いがあります:jsperf.com/create-an-array-of-initial-size/2
Marco Luglio

4
確かに、しかし、私がそれらを追加するほとんどの場所でセミコロンや改行を必要としません。一貫性と読みやすさについてです。ねえ、私見。
nickf 2013年

774

暗黙的な配列で配列を作成することと配列コンストラクターを作成することの違いは微妙ですが重要です。

を使用して配列を作成するとき

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」がアラートされます。2番目はしません。あなたは未定義を見ることになります。また、bにはなどのネイティブのArrayオブジェクト関数がすべて含まれているのにpush、他には含まれていないことに注意してください。

これが起こることを期待するかもしれませんが、それ[]はと同じではないという事実を示しているにすぎませんnew Array()

[]配列が必要なことがわかっている場合は、おそらくそれだけを使用するのが最善です。また、アレイを回避して再定義することはお勧めしません...


157
まあ、私は知っていると思います。どのような人が配列クラスを上書きするかわかりません...
nickf

160
あなたは絶対的に正しいです。狂人だけが配列クラスを上書きします。ここで少し時間を取って、new Array()を使用するすべての余分な作業を考慮して、インタプリタがこれらの狂人をサポートするようにします。私はそれを[]と一緒に避けるだけです。
coderjoe 2009

51
JavaScriptで可能な地球規模の汚染の良い例です。
David Snabel-Caunt、2010

8
新しいArray(size)は、[]表記を使用する他の可能なメソッドよりも高速であることに注意してください。出典:jsperf.com/create-an-array-of-initial-size/2
Marco Luglio

9
残念ながら、そのテストは不適切に準備されています。配列の初期化とそれに続く配列アクセスを使用して、配列の初期化をテストしています。ブラウザが実際にメモリを事前に割り当てていることを証明する方法はありません(仕様ではそうする必要があるとは記載されていません)。配列へのアクセスが一定であり、ほとんどの時間がメモリの割り当てに両方の例で費やされると想定できる場合、数百万の配列をインスタンス化する場合は[]の方が望ましいでしょう。 jsperf.com/array-instanciation
coderjoe

95

答えがまだ述べられていない重要な違いがあります。

これから:

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仕様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]

22
あなたの答えが唯一の実際の答え
ビクター

これは理にかなっています。文書化された参照が見つからない別の構成にぶつかっただけです。[...Array(2)]これは[undefined, undefined]結果の観点からは同等です。
Roberto Andrade

私の以前のコメントへの回答は「スプレッドオペレーター」のようです。javascript.info
Roberto Andrade

@RobertoAndradeは、spreadオペレーターがそのようなコピーを適用できるようにエントリを読み取る必要があるため、意味があります。このような空のスロットを読み取るとundefined、通常どおり戻ります。
Hux

51

奇妙なことに、Chromeのnew Array(size)ほぼ2倍の速さで[]、FFとIEでほぼ同じです(配列を作成して埋めることで測定)。配列のおおよそのサイズがわかっている場合にのみ問題になります。指定した長さよりも多くのアイテムを追加すると、パフォーマンスの向上は失われます。

より正確にArray(は、メモリを割り当てない高速の一定時間操作であり、wheras []はタイプと値を設定する線形時間操作です。


3
私はNode.jsで多くのテストを行いました:new Array(length)0 <=サイズ<= []
〜1000


40

詳細については、次のページで使用する必要がない理由を説明していますnew Array()

new Object()JavaScriptで使用する必要はありません。{} 代わりにオブジェクトリテラルを使用してください。同様に、を使用せずnew Array()[] 代わりに配列リテラルを使用してください。JavaScriptの配列は、Javaの配列のようには機能せず、Javaのような構文を使用すると混乱します。

使用しないでくださいnew Numbernew Stringまたは new Boolean。これらのフォームは、不要なオブジェクトラッパーを生成します。代わりに単純なリテラルを使用してください。

また、コメントも確認してください- new Array(length)フォームは(少なくとも今日のJavaScriptの実装では)有用な目的を果たしていません。


3
Crockfordも、新しいArray()ではなく[]を使用するように言っています。残念ながら、彼はリンクされた記事でその理由を述べていません。スペースと速度の問題だと思います。javascript.crockford.com/code.html
Nosredna 2009年

4
Crockfordは、「new」キーワードを使用してJavascriptでオブジェクトの新しいインスタンスを作成するのが好きではありません。講義で彼はそれが曖昧さを生み出し、JavaScriptのプロトタイプスタイルの継承とうまく適合しないと彼の信念であると述べました。彼はユーザーが作成したオブジェクトコンストラクターを具体的に参照していますが、その信念を考えると、代替構文がある場合に組み込み関数でも使用しないことをお勧めする理由は簡単にわかります。
アランストーム

@Alan Storm:少なくともNumber、String、およびBooleanについては、「これらのフォームは不要なオブジェクトラッパーを生成する」と述べていますが、これは配列には当てはまらないと思います。
BarelyFitz 2009年

10

よりよく理解し[]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コンソールからのものです。


4
しかし、なぜ[] == []または[] === []が間違っているのですか?
anu

5
「オブジェクトを比較する式は、オペランドが同じオブジェクトを参照する場合にのみ真になります。」(ソース:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
srph '20 / 11/15

この答えは、2つの構成が同一であることを暗示する例を選びます。以下のような違いアウトこのページポイントの他の記事、Array(3)またはnew Array(3)同じではありません[3]
ggorlen

8

1つ目は、デフォルトのオブジェクトコンストラクター呼び出しです。必要に応じて、パラメータを使用できます。

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

2つ目は、空ではない配列を作成する機能を提供します。

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

1
冗長コンストラクターでも同じことができます。var array = new Array(1、2、3);
nickf 2009年

したがってvar array = [5]、角かっこを使用して、コンストラクタを使用せずvar array = Array(5)に5つの要素の空の配列を作成できると思います。
cdmckay 2009年

cdmckay-不正解です。var a = [5]は、単一の項目(数値5)の配列になります。
BarelyFitz、2009年

2
@BarelyFitz:それは私が言ったことです。ボグダンの答えでは、配列を初期化するためにコンストラクター呼び出しを使用することはできないと彼は言いましたが、彼は間違っていました。私のコメントは、コンストラクター呼び出しを使用して単一要素の配列を初期化できないことを明確にすることだけでした。
cdmckay 2009年

1
@cdmckay:すみません、あなたのコメントを誤解しました。明確にするため:new Array(arg)-argが数値の場合、これによりlength = argの空の配列が作成されます。new Array(arg1、arg2)-新しい配列を作成し、配列要素を初期化します。そのため、[5]のような1つの数値要素を持つ配列を作成する場合、new Array(5)を使用してそれを行うことはできません。しかし、実際にはnew Array()を使用しないでください。
BarelyFitz 2009年

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

配列に別の値を追加し、4つのアラートを作成しました。1つ目と2つ目は、各配列に格納されている値を提供し、値を確認することです。彼らは同じを返します!今度は3番目のものを試してください。それはfalseを返します。それは、

JSはtest1データ型arrayのVARIABLEとして扱い、test2配列の機能を持つOBJECTとして扱いますが、ここではわずかな違いがあります。

最初の違いは、test1を呼び出すと、何も考えずに変数を呼び出し、データ型に関係なく、この変数に格納されている値を返すだけです。ただし、test2を呼び出すと、Array()関数が呼び出され、「プッシュ」された値が「値」プロパティに格納されます。test2にアラートを出すと同じことが起こり、配列オブジェクトの「値」プロパティが返されます。

したがって、test1がtest2と等しいかどうかを確認すると、もちろんtrueが返されることはありません。一方は関数であり、もう一方は変数です(配列のタイプを使用)。たとえ同じ値であっても!

これを確実にするには、.valueを追加した4番目のアラートを試してください。trueを返します。この場合、JSに「関数か変数かに関係なく、コンテナーのタイプを無視して、各コンテナーに格納されている値を比較して、表示された内容を教えてください!」と伝えます。それがまさに何が起こるかです。

私はその背後にある考えをはっきりと述べてほしいと思います、そして私の悪い英語を申し訳ありません。


19
そのような完全でナンセンスなものが投票されたことは驚くべきことです。配列間の比較は、オブジェクトIDを比較し、それらが異なるオブジェクトであるため、どのように作成しても偽になります。配列には値のプロパティはありません。[]そしてnew Array()同一です; .valueなりますundefinedどちらの場合も、それらを比較することは常にfalseとなります。
2015

同意されたとおり、この答えは意味がなく、何も示しません。のようなものはありませんarray.value。と両方typeof []typeof new Array()戻りobjectます。これが呼び出される関数がある理由の1つですArray.isArray
gman

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

3

最初のものは、デフォルトのオブジェクトコンストラクターコールです。主に動的な値に使用されます。

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

2番目の配列は、静的な値を作成するときに使用されます

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

3

大きな違いはありません。基本的に同じことを行いますが、方法は異なりますが、W3Cで次のステートメントを読んでください。

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

そして

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

上記の2つの例はまったく同じです。new Array()を使用する必要はありません。
単純化、読みやすさ、実行速度のために、最初の方法(配列リテラルメソッド)を使用してください。

しかし、同時にnew Array、悪い習慣と見なされている構文を使用して新しい配列を作成します。

新しいArray()を避ける

JavaScriptの組み込み配列コンストラクターnew Array()を使用する必要はありません。
代わりに[]を使用してください。
次の2つの異なるステートメントはどちらも、pointsという名前の新しい空の配列を作成します。

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

これら2つの異なるステートメントはどちらも、6つの数値を含む新しい配列を作成します。

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

新しいキーワードは、コードを複雑にします。また、予期しない結果が生じることもあります。

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

要素の1つを削除するとどうなりますか?

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

したがって、基本的にはベストプラクティスとは見なされません。また、小さな違いが1つあります。長さをnew Array(length)このように渡すことができますが、これも推奨される方法ではありません。


こんにちはAlireza、これらはどこからコピーして貼り付けていますか?テキストのコピー元のページへのリンクを追加してください。詳細については、ヘルプセンターのページをご覧ください。ありがとうございました。
2017年

有用new Array(40).fill(123)
gman

2

使用の違い

var arr = new Array(size);

または

arr = [];
arr.length = size;

この質問で十分に議論されたように。

速度の問題を追加したいと思います。現在の最速の方法google chromeは、2番目の方法です。

しかし、注意してください。これらは更新により大きく変化する傾向があります。また、ランタイムはブラウザによって異なります。

たとえば、私が言及した2番目のオプションは200万[オペレーション/秒]でchrome実行されmozilla dev.ますが、試してみると、驚くほど2300万という高いレートが得られます。

とにかく、私はあなたがそれを時々、さまざまなブラウザ(とマシン)で、そのようなサイト使ってチェックアウトすることをお勧めします


2

私はdiferenceを知っているようにuがのようなスライス(またはアレイの他のつく)を見つけることができますCODE1 .AND コード2 Uを表示アレイと彼のインスタンスを

code1:

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

code2:

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

結論:

Arrayの新しいインスタンスを表示[]してnew Array()作成できるので、すべてのプロトタイプ関数を取得しますArray.prototype

それらはArray.soの単なる異なるインスタンスなので、これが理由を説明しています [] != []

:)


2

[]を使用して奇妙な動作が発生しました。

モデルに「クラス」があり、フィールドがいくつかの値に初期化されています。例えば:

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

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

フィールドを初期化すると[]、すべてのモデルオブジェクトで共有されることがわかりました。1つに変更を加えると、他のすべてに影響します。

これは、で初期化されることはありませんnew Array()。オブジェクトの初期化についても同じ({}vs new Object()

TBH使用していたフレームワーク(Dojo)に問題があるかどうかはわかりません


2

これには、目に見える以上のものがあります。他のほとんどの答えは正しいですが、また ..

new Array(n)

  • エンジンがn要素にスペースを再割り当てできるようにします
  • アレイ作成用に最適化
  • 作成された配列は、最もパフォーマンスの低い配列操作を持つスパースとしてマークされます。これは、各インデックスアクセスが境界をチェックし、値が存在するかどうかを確認して、プロトタイプチェーン歩くためです。
  • 配列がスパースとしてマークされている場合、戻ることはできません(少なくともV8では)、1ミリ秒または2時間後にコンテンツ(パックされた配列)でいっぱいになったとしても、存続期間中は常に遅くなります。

[1, 2, 3] || []

  • 作成された配列はパック済みとしてマークされますdeleteまたは[1,,3]構文を)
  • 配列のために最適化操作for ..forEachmap、など)
  • アレイが大きくなると、エンジンはスペースを再割り当てする必要があります

これはおそらく、古いバージョンのブラウザ/ブラウザには当てはまりません。


-2

2つの構造に1つの違いがあり、かなり苦労しました。

私が持っているとしましょう:

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

言語仕様がどうなるかはわかりませんが、2つのオブジェクトにオブジェクトの一意のプロパティ配列を持たせたい場合は、を使用する必要がありますnew Array()


このJSFiddleは、出力が配列リテラル[]new Array()コンストラクターで期待されるものであり、プロパティごとに配列ごとに1つの項目が生成されることを示しています。上に示した結果を得るには、コードで何か他のことが行われている必要があります。
gfullam 2015

バッキー、それは私には起こりません、どのブラウザでも。:その動作を取得するには、このような何かしなければならないだろう var property1static=[]; function MyClass(){ this.property1=property1static; this.property2=new Array(); };
デイブ・バートン

-3

Arrayコンストラクターを使用すると、必要な長さの新しい配列が作成され、各インデックスに未定義が設定されます。変数に配列を割り当てると、情報を提供するインデックスが作成されます。


1
いいえ、配列は設定されていません。内部にインデックス/キーはありません。たとえば、.forEachは機能しません。
CFrei
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.