配列

意味

配列とは、値を順番に並べたものです。各値の位置には (0 から始まる) 番号が付けられ、配列全体は角かっこで表されます。

var arr = ['a', 'b', 'c'];

上記コードの「a」、「b」、「c」は配列を構成しており、両端の角括弧は配列の記号です。 「a」は位置 0、「b」は位置 1、「c」は位置 2 です。

定義時に値を割り当てるだけでなく、配列を最初に定義してから割り当てることもできます。

var arr = [];

arr[0] = 'a';
arr[1] = 'b';
arr[2] = 'c';

任意のタイプのデータを配列に配置できます。

var arr = [
  {a: 1}、
  [123]、
  function() {true を返す;}
];

arr[0] // オブジェクト {a: 1}
arr[1] // [1, 2, 3]
arr[2] // function (){return true;}

上記の配列 arr の 3 つのメンバーは、順にオブジェクト、配列、関数です。

配列の要素がまだ配列である場合は、多次元配列が形成されます。

var a = [[1, 2], [3, 4]];
a[0][1] // 2
a[1][1] // 4

配列の性質

基本的に、配列は特別な種類のオブジェクトです。 typeof 演算子は、配列の型を object として返します。

typeof [1, 2, 3] // "オブジェクト"

上記のコードは、「typeof」演算子が配列の型をオブジェクトとみなしていることを示しています。

配列の特徴は、そのキーが順番に配置された一連の整数 (0、1、2...) であることです。

var arr = ['a', 'b', 'c'];

オブジェクト.キー(arr)
// ["0", "1", "2"]

上記のコードでは、「Object.keys」メソッドは配列のすべてのキー名を返します。配列のキー名が整数 0、1、2 であることがわかります。

配列メンバーのキー名は固定されているため (デフォルトは常に 0、1、2...)、配列では各要素にキー名を指定する必要はありませんが、オブジェクトの各メンバーはキー名を指定する必要があります。 JavaScript 言語では、オブジェクトのキー名は常に文字列であると規定されているため、配列のキー名は実際には文字列になります。数値で読み込める理由は、文字列以外のキー名を文字列に変換してしまうためです。

var arr = ['a', 'b', 'c'];

arr['0'] // 'a'
arr[0] // 'a'

上記のコードはキー名として数値と文字列をそれぞれ使用しており、結果を配列から読み込むことができます。その理由は、数値キー名が自動的に文字列に変換されるためです。

これは値を割り当てる場合にも当てはまります。値は常に最初に文字列に変換されてから、キー名として割り当てられます。

var a = [];

a[1.00] = 6;
a[1] // 6

上記コードでは、「1.00」が文字列に変換され「1」となっているので、テンキー「1」で値を読み取ることができます。

前の章で述べたように、オブジェクトにはメンバーを読み取るための 2 つのメソッドがあります。ドット構造 (object.key) と角括弧構造 (object[key]) です。ただし、数値キー名にはドット構造は使用できません。

var arr = [1, 2, 3];
arr.0 // 構文エラー

上記のコードでは、単一の値を識別子として使用できないため、「arr.0」の書き込みは不正です。したがって、配列メンバーは角括弧 arr[0] でのみ表すことができます (角括弧は演算子であり、数値を受け入れることができます)。

長さ属性

配列の「length」プロパティは、配列のメンバーの数を返します。

['a', 'b', 'c'].length // 3

JavaScript は 32 ビット整数を使用して配列内の要素の数を格納します。これは、配列メンバーの最大数が 4294967295 (232 - 1) であることを意味します。これは、length 属性の最大値が 4294967295 であることを意味します。

配列である限り、「length」属性が必要です。この属性は、キー名の最大の整数に「1」を加えた動的な値です。

var arr = ['a', 'b'];
arr.length // 2

arr[2] = 'c';
arr.length // 3

arr[9] = 'd';
arr.length // 10

arr[1000] = 'e';
arr.length // 1001

上記のコードは、配列の数値キーが連続している必要がなく、「length」属性の値が常に最大の整数キーよりも「1」大きいことを示しています。さらに、これは、配列が動的データ構造であり、配列のメンバーがいつでも追加または削除できることも示しています。

length プロパティは書き込み可能です。現在のメンバー数よりも小さい値を手動で設定すると、配列内のメンバー数は length で設定された値まで自動的に減ります。

var arr = [ 'a', 'b', 'c' ];
arr.length // 3

arr.length = 2;
arr // ["a", "b"]

上記のコードは、配列の length プロパティが 2 に設定されている (つまり、最大の整数キーは 1 のみである) 場合、整数キー 2 (値は c) が配列内に存在しないことを示しています。そして自動的に削除されます。

配列をクリアする効果的な方法は、length プロパティを 0 に設定することです。

var arr = [ 'a', 'b', 'c' ];

arr.length = 0;
arr // []

「length」が現在の要素数よりも大きくなるように手動で設定されている場合、配列のメンバーの数はこの値まで増加し、新しい位置は空になります。

var a = ['a'];

a.長さ = 3;
a[1] // 未定義

上記のコードは、length プロパティが配列の数より大きく設定されている場合、新しく追加された位置を読み取ると unknown が返されることを示しています。

「length」が手動で不正な値に設定された場合、JavaScript はエラーを報告します。

//負の値を設定する
[].length = -1
// RangeError: 配列の長さが無効です

//配列要素の数は 2 の 32 乗以上です
[].length = Math.pow(2, 32)
// RangeError: 配列の長さが無効です

//文字列を設定する
[].length = 'abc'
// RangeError: 配列の長さが無効です

配列は本質的にオブジェクトであるため、配列にプロパティを追加できますが、これは「length」プロパティの値には影響しないことに注意してください。

var a = [];

a['p'] = 'abc';
a.length // 0

a[2.1] = 'abc';
a.length // 0

上記のコードは、配列のキーをそれぞれ文字列と 10 進数に設定し、その結果は length プロパティには影響しません。 「length」プロパティの値は最大の数値キーに 1 を加えたものに等しく、この配列には整数キーがないため、「length」プロパティは「0」のままです。

配列のキー名に範囲外の値を追加する場合、キー名は自動的に文字列に変換されます。

var arr = [];
arr[-1] = 'a';
arr[Math.pow(2, 32)] = 'b';

arr.length // 0
arr[-1] // "a"
arr[4294967296] // "b"

上記のコードでは、2 つの不正な数値キーを配列 arr に追加しました。その結果、length 属性は変更されませんでした。これらの数値キーは文字列キー名になりました。最後の 2 行で値を取得する理由は、キー値を取得するときに、デフォルトで数値キー名が文字列に変換されるためです。

演算子内

キー名が存在するかどうかをチェックする演算子「in」は、配列だけでなくオブジェクトにも適用されます。

var arr = [ 'a', 'b', 'c' ];
2 in arr // true
arr の '2' // true
4 in arr // false

上記のコードは、配列に「2」という名前のキーがあることを示しています。キー名はすべて文字列であるため、値「2」は自動的に文字列に変換されます。

配列内の位置が空の場合、「in」演算子は「false」を返すことに注意してください。

var arr = [];
arr[100] = 'a';

100 in arr // true
1 in arr // false

上記のコードでは、配列 arr にはメンバー arr[100] が 1 つだけあり、他の位置のキー名は false を返します。

for...in ループと配列のトラバーサル

for...in ループはオブジェクトだけでなく配列も走査できます。結局のところ、配列は単なる特別なオブジェクトです。

var a = [1, 2, 3];

for (var i in a) {
  console.log(a[i]);
}
// 1
// 2
// 3

ただし、「for...in」は配列のすべての数値キーを走査するだけでなく、数値以外のキーも走査します。

var a = [1, 2, 3];
a.foo = true;

for (a の var key) {
  コンソール.ログ(キー);
}
// 0
// 1
// 2
// ふー

上記のコードが配列を走査するとき、非整数キー foo も走査します。したがって、配列を走査するために「for...in」を使用することはお勧めできません。

配列の走査には、「for」ループまたは「while」ループの使用を検討してください。

var a = [1, 2, 3];

// for ループ
for(var i = 0; i < a.length; i++) {
  console.log(a[i]);
}

// while ループ
変数 i = 0;
while (i < a.length) {
  console.log(a[i]);
  i++;
}

var l = a.length;
一方 (l--) {
  console.log(a[l]);
}

上記のコードは、配列を走査する 3 つの方法です。これを記述する最後の方法は、逆にトラバースすることです。つまり、最後の要素から最初の要素までトラバースします。

配列の forEach メソッドを使用して配列を走査することもできます。詳細については、「標準ライブラリ」の「配列オブジェクト」の章を参照してください。

var Colors = ['red', 'green', 'blue'];
color.forEach(関数 (色) {
  コンソール.ログ(色);
});
// 赤
// 緑
// 青

配列内の空の位置

配列内の特定の位置に空の要素がある場合、つまり 2 つのカンマの間に値がない場合、配列に穴があるといいます。

var a = [1, , 1];
a.length // 3

上記のコードは、配列内の空のスペースが「length」プロパティに影響を与えないことを示しています。この位置には値がありませんが、エンジンはこの位置が有効であるとみなします。

最後の要素の後にカンマがある場合、ギャップは生成されないことに注意してください。つまり、カンマがあってもなくても結果は同じになります。

var a = [1, 2, 3,];

a.length // 3
a // [1、2、3]

上記のコードでは、配列の最後のメンバーの後にカンマがありますが、これは「length」プロパティの値には影響せず、カンマがない場合と同じ効果があります。

配列内の空の位置を読み取ることができ、「未定義」を返します。

var a = [, , ,];
a[1] // 未定義

delete コマンドを使用して配列メンバーを削除すると、ギャップが作成されますが、length プロパティには影響しません。

var a = [1, 2, 3];
a[1] を削除します。

a[1] // 未定義
a.length // 3

上記のコードは delete コマンドを使用して配列の 2 番目の要素を削除しますが、この位置にギャップが形成されますが、これは length 属性には影響しません。つまり、「length」プロパティはギャップを除外しません。したがって、配列の走査に length プロパティを使用するときは、十分に注意する必要があります。

配列内の特定の位置が空であることと、特定の位置が「未定義」であることには違いがあります。空の位置の場合は、配列の forEach メソッド、for...in 構造体、および Object.keys メソッドを使用して走査すると、空の位置はスキップされます。

var a = [, , ,];

a.forEach(関数 (x, i) {
  console.log(i + '. ' + x);
})
// 何も出力しません

for (var i in a) {
  コンソール.ログ(i);
}
// 何も出力しません

オブジェクト.キー(a)
//[]

特定の位置が「未定義」の場合、その位置はトラバース中にスキップされません。

var a = [未定義、未定義、未定義];

a.forEach(関数 (x, i) {
  console.log(i + '. ' + x);
});
// 0.未定義
// 1.未定義
// 2.未定義

for (var i in a) {
  コンソール.ログ(i);
}
// 0
// 1
// 2

オブジェクト.キー(a)
// ['0', '1', '2']

つまり、空の位置は配列にこの要素がないため走査されないことを意味し、「未定義」は配列にこの要素があり、値が「未定義」であるため走査されないことを意味します。スキップしてください。

配列のようなオブジェクト

オブジェクトのすべてのキーが正の整数またはゼロで、「length」プロパティを持つ場合、そのオブジェクトは配列に非常によく似ており、構文的には「配列状オブジェクト」と呼ばれます。

var obj = {
  0: 'a'1: 「b」、
  2: 「c」、
  長さ: 3
};

obj[0] // 'a'
obj[1] // 'b'
obj.length // 3
obj.push('d') // TypeError: obj.push は関数ではありません

上記のコードでは、オブジェクト obj は配列のようなオブジェクトです。ただし、「配列のようなオブジェクト」は配列固有のメソッドを持たないため、配列ではありません。オブジェクト obj には配列の push メソッドがありません。このメソッドを使用するとエラーが報告されます。

「配列状オブジェクト」の基本的な特徴は、「長さ」プロパティを持つことです。 「length」プロパティがある限り、オブジェクトは配列と同様であると考えることができます。しかし、問題があります。この「length」プロパティは動的値ではないため、メンバーが変更されても変化しません。

var obj = {
  長さ: 0
};
obj[3] = 'd';
obj.length // 0

上記のコードは数値キーをオブジェクト obj に追加しますが、length プロパティは変更されません。これは、「obj」が配列ではないことを示しています。

典型的な「配列のようなオブジェクト」は、関数の引数オブ​​ジェクト、DOM 要素のほとんどのセット、および文字列です。

//引数オブジェクト
関数 args() { 引数を返す }
var arrayLike = args('a', 'b');

arrayLike[0] // 'a'
arrayLike.length // 2
arrayLike 配列のインスタンス // false

// DOM 要素セット
var elts = document.getElementsByTagName('h3');
elts.length // 3
elts 配列のインスタンス // false

// 弦
'abc'[1] // 'b'
'abc'.length // 3
'abc' 配列のインスタンス // false

上記のコードには 3 つの例が含まれていますが、どれも配列ではありません (「instanceof」演算子は「false」を返します)。しかし、それらはすべて配列によく似ています。

配列の slice メソッドは、「配列のようなオブジェクト」を実際の配列に変えることができます。

var arr = Array.prototype.slice.call(arrayLike);

実際の配列への変換に加えて、「配列のようなオブジェクト」が配列メソッドを使用する別の方法があります。それは、call() を通じてオブジェクトに配列メソッドを配置することです。

関数 print(値, インデックス) {
  console.log(インデックス + ' : ' + 値);
}

Array.prototype.forEach.call(arrayLike, print);

上記のコードでは、「arrayLike」は配列のようなオブジェクトを表します。本来は配列の「forEach()」メソッドは使用できませんが、「call()」を介して「forEach()」を「arrayLike」に移植できます。 `。

次の例では、このメソッドを使用して、arguments オブジェクトの forEach メソッドを呼び出します。

// forEach メソッド
関数 logArgs() {
  Array.prototype.forEach.call(arguments, function (elem, i) {
    console.log(i + '. ' + elem);
  });
}

// for ループと同等
関数 logArgs() {
  for (var i = 0; i < argument.length; i++) {
    console.log(i + '. ' + 引数[i]);
  }
}

文字列も配列のようなオブジェクトなので、「Array.prototype.forEach.call」を使用して走査することもできます。

Array.prototype.forEach.call('abc', function (chr) {
  コンソール.ログ(chr);
});
//
//b
//c

このメソッドは、配列のネイティブ forEach を直接使用するよりも遅いことに注意してください。そのため、最初に「配列のようなオブジェクト」を実際の配列に変換してから、配列の forEach メソッドを直接呼び出すのが最善です。

var arr = Array.prototype.slice.call('abc');
arr.forEach(関数 (chr) {
  コンソール.ログ(chr);
});
//
//b
//c

参考リンク


作者: wangdoc

アドレス: https://wangdoc.com/

ライセンス: クリエイティブ・コモンズ 3.0