私がJavaScript( w3schools および devguru を含む)で配列について読んだチュートリアルのほとんどは、var test = new Array(4);
構文を使用してArrayコンストラクターに整数を渡すことで、一定の長さで配列を初期化できることを示します。 。
私のjsファイルでこの構文を寛大に使用した後、 jsLint を介してファイルの1つを実行し、それがおかしくなりました。
エラー:1行目の文字22に問題があります: ')'が予期されていましたが、 '4'が表示されました。
var test = new Array(4);
1行目の文字23の問題: ';'が必要ですそして代わりに ')'を見ました。
var test = new Array(4);
1行目の文字23の問題:識別子が必要ですが、代わりに ')'が表示されました。
jsLintの動作説明 を読んでみると、jsLintはnew Array()
構文にはあまり似ていないように見え、代わりに配列を宣言するときは[]
を優先します。
だから私はいくつか質問があります。まず、なぜ?代わりにnew Array()
構文を使用して危険を冒していますか?注意すべきブラウザの非互換性はありますか?次に、角括弧の構文に切り替えると、配列を宣言してその長さをすべて1行に設定する方法があります。または、次のようにする必要があります。
var test = [];
test.length = 4;
なぜ長さを初期化するのですか?理論的にはこれは必要ありません。 length
を使用して配列が空であるかどうかを調べるすべてのテストは、配列が空でないことを報告するため、動作が混乱する可能性さえあります。
Sometests は、大きな配列の初期の長さを設定することを示しますcan 配列が後で満たされる場合はより効率的ですが、パフォーマンスの向上(ある場合)はブラウザーごとに異なるようです。
jsLintはnew Array()
を好みません。これは、コンストラクタがあいまいだからです。
new Array(4);
空の配列を作成します長さ 4。
new Array('4');
配列を作成します値を含む'4'
。
コメントについて:JSでは、配列の長さを初期化する必要はありません。それは動的に成長します。長さを何らかの変数に保存することができます。
var data = [];
var length = 5; // user defined length
for(var i = 0; i < length; i++) {
data.Push(createSomeObject());
}
Array(5)
は長さ5の配列を与えますが、値は与えないので、それを反復することはできません。
Array.apply(null, Array(5)).map(function () {})
は、長さ5で値として未定義の配列を返します。これで、配列の繰り返しが可能になりました。
Array.apply(null, Array(5)).map(function (x, i) { return i; })
は、長さ5、値0、1、2、3、4の配列を返します。
Array(5).forEach(alert)
は何もしません、Array.apply(null, Array(5)).forEach(alert)
はあなたに5つのアラートを与えます
ES6
は私達にArray.from
を与えるので、今またあなたはArray.from(Array(5)).forEach(alert)
を使うことができます
あなたが特定の値で初期化したいならば、これらは知っているのが良いです...Array.from('abcde')
、Array.from('x'.repeat(5))
またはArray.from({length: 5}, (v, i) => i) // gives [0, 1, 2, 3, 4]
ES2015.fill()
を使用すると、簡単に実行できます。
// `n` is the size you want to initialize your array
// `0` is what the array will be filled with (can be any other value)
Array(n).fill(0)
これはArray.apply(0, new Array(n)).map(i => value)
よりずっと簡潔です
.fill()
に0
をドロップして引数なしで実行すると、配列にundefined
が入ります。 ( ただし、TypeScriptでは失敗します )
最も短い:
[...Array(1000)]
ES6では Array.from
が導入され、 "array-like" または iterables オブジェクトからArray
を作成できます。
Array.from({length: 10}, (x, i) => i);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
この場合、{length: 10}
は、 "array-like" objectの最小定義を表します。これは、length
プロパティのみが定義された空のオブジェクトです。
Array.from
は、結果の配列をマップするための2番目の引数を許可します。
[...Array(6)].map(x=>0);
// [0, 0, 0, 0, 0, 0]
_または_
Array(6).fill(0);
// [0, 0, 0, 0, 0, 0]
注:空のスロットをループすることはできませんArray(4).forEach( (_,i) => {} )
_または_
Array(6).fill(null).map( (x,i) => i );
// [0, 1, 2, 3, 4, 5]
( TypeScriptセーフ )
fill
で 2D 配列を直感的に作成するときは、新しいインスタンスを作成する必要があります。しかし実際には、同じ配列が参照として格納されます。
var a = Array(3).fill([6]);
// [[6], [6], [6]]
a[ 0 ].Push( 9 );
// [[6,9], [6,9], [6,9]]
溶液
var a = [...Array(3)].map(x=>[]);
a[ 0 ].Push( 4, 2 );
// [[4,2], [ ], [ ]]
したがって、3x2の配列はこのようになります。
[...Array(3)].map(x=>Array(2).fill(0));
// [ [0,0] ,
// [0,0] ,
// [0,0] ]
これはlengthプロパティを4に初期化します。
var x = [,,,,];
1行で長さを設定できる機能的な解決策が提案されていないのは驚きです。以下はUnderscoreJSに基づいています。
var test = _.map(_.range(4), function () { return undefined; });
console.log(test.length);
上記の理由から、配列を特定の値に初期化したいのでなければ、これを避けることができます。興味深いことに、Lo-dashやLazyなど、rangeを実装しているライブラリは他にもありますが、これらには異なるパフォーマンス特性があります。
(これはおそらくコメントとしては良かったのですが、長すぎました)
それで、これを読んだ後、私は事前割り当てが実際に速いかどうかに興味がありました。理論的にはそうすべきだからです。しかしながら、このブログはそれに対して助言するいくつかの助言を与えました http://www.html5rocks.com/en/tutorials/speed/v8/ 。
まだわからないので、私はそれをテストにかけました。そして結局のところ、実際には遅くなるようです。
var time = Date.now();
var temp = [];
for(var i=0;i<100000;i++){
temp[i]=i;
}
console.log(Date.now()-time);
var time = Date.now();
var temp2 = new Array(100000);
for(var i=0;i<100000;i++){
temp2[i] = i;
}
console.log(Date.now()-time);
このコードは、何度か実行した後に次のようになります。
$ node main.js
9
16
$ node main.js
8
14
$ node main.js
7
20
$ node main.js
9
14
$ node main.js
9
19
var arr=[];
arr[5]=0;
alert("length="+arr.length); // gives 6
人々があなたの古い習慣をまだあきらめないでください。一度メモリを割り当ててからその配列内のエントリを処理すること(古い時点)と、配列が大きくなるにつれて何度も割り当てることとの間には速度の大きな違いがあります。 。
あなたがより大きなアレイで何かクールなことをしたいと思うまではもちろん、これは重要ではありません。それはします。
現時点ではまだ配列の初期容量を設定するためのオプションがないように思われるので、私は以下を使用します...
var newArrayWithSize = function(size) {
this.standard = this.standard||[];
for (var add = size-this.standard.length; add>0; add--) {
this.standard.Push(undefined);// or whatever
}
return this.standard.slice(0,size);
}
関係するトレードオフがあります。
standard
配列は、あなたが要求した最大の配列と同じ大きさのスペースを永久に確保します。しかしそれがあなたがしていることに合うならば、そこに利益があるかもしれません。非公式のタイミング
for (var n=10000;n>0;n--) {var b = newArrayWithSize(10000);b[0]=0;}
かなり速い(n = 1000000の場合、約5秒かかることを考えると、10000で約50ms)
for (var n=10000;n>0;n--) {
var b = [];for (var add=10000;add>0;add--) {
b.Push(undefined);
}
}
1分をはるかに超えて(同じクロムコンソールの10000で約90秒、または約2000倍遅くなります)。それは割り当てだけではなく、10000プッシュ、forループなどにもなります。
これは別の解決策です
var arr = Array.apply( null, { length: 4 } );
arr; // [undefined, undefined, undefined, undefined] (in Chrome)
arr.length; // 4
apply()
の最初の引数はthisオブジェクトのバインディングです。これについてはここでは気にしないので、それをnull
に設定します。
Array.apply(..)
はArray(..)
関数を呼び出し、その引数として{ length: 3 }
オブジェクト値を展開しています。
配列コンストラクタは あいまいな構文 を持ち、JSLintは結局あなたの気持ちを傷つけます。
また、あなたのサンプルコードは壊れています、2番目のvar
ステートメントはSyntaxError
を上げます。配列length
のプロパティtest
を設定しているので、別のvar
は必要ありません。
あなたの選択に関する限り、array.length
は唯一の「きれいな」ものです。問題は、なぜそもそもサイズを設定する必要があるのですか?その依存関係を取り除くためにコードをリファクタリングしてみてください。
配列の長さが一定であると仮定します。 Javascriptでは、これが私たちの行動です。
const intialArray = new Array(specify the value);
上で説明したように、new Array(size)
を使うことはいくぶん危険です。直接使うのではなく、「配列作成関数」の中に置いてください。この関数にバグがないことを簡単に確認でき、new Array(size)
を直接呼び出す危険性を回避できます。また、オプションのデフォルト初期値を指定することもできます。このcreateArray
関数はまさにそれを行います。
function createArray(size, defaultVal) {
var arr = new Array(size);
if (arguments.length == 2) {
// optional default value
for (int i = 0; i < size; ++i) {
arr[i] = defaultVal;
}
}
return arr;
}
new Array
を使用してはいけない理由は、次のコードで実証されています。
var Array = function () {};
var x = new Array(4);
alert(x.length); // undefined...
他のコードArray変数を混乱させる可能性があります。誰かがそのようなコードを書くことになるのは少し先んじていますが、それでも...
また、Felix Kingが言ったように、インタフェースは少し矛盾していて、追跡するのが非常に難しいバグを引き起こす可能性があります。
(new Array(x)
のように)未定義値で埋められた、length = xの配列が欲しいなら、これを行うことができます:
var x = 4;
var myArray = [];
myArray[x - 1] = undefined;
alert(myArray.length); // 4