JavaScriptの配列
JavaScriptの配列
JavaScriptの配列には型はないため、配列の要素にはどの型の値でも格納できる。つまり、配列の要素にオブジェクトやほかの配列を格納することも可能。
JavaScirptの配列のインデックスは0から始まり、32ビットの整数値になる。つまり最大のインデックス値は4294967294(2^32-2)となる つまり最大4294967295個の要素を持つ配列を生成することができる。 また、処理時に数値インデックスを文字列に変換、その後この文字列をプロパティ名として使用する。
JavaScriptの配列は動的である 配列の生成時に配列の長さを湖底で指定する必要がないかつ長さを変更するときに再割り当てする必要もない また、配列は疎(つまり最初から最後まで連続して要素が格納されていない)でも問題ない
配列はすべてlengthプロパティを持ち、疎ではない配列の場合、lengthは単純に配列の要素数を表す一方、疎な配列の場合、lengthは格納されていない要素を含めた配列の要素数を表す
また配列はArray.prototypeからプロパティを継承し、このプロトタイプには配列を操作するためのメソッドが用意されている これらのメソッドの大半は汎用的で、配列以外の配列の様なオブジェクト(§7.9参照)にも適用できる 文字列は実は文字の配列のようなふるまいをする(§7.10参照)
ES2015では、「型付き配列」という新たな配列クラスが追加された 通常の配列とは異なり型付き配列は固定の長さを持ち、要素は固定の数値型になる 型付き配列を使うとバイナリデータを高速に処理したり、バイト単位でアクセスできるようになる 型付き配列は§11.2参照
配列は特殊なオブジェクトであり両者には共通点がある 例えば配列の要素にアクセスする[]演算子はオブジェクトのプロパティにアクセスする[]演算子と同じように動作する ただし、配列とオブジェクトは共通部分もあるが異なる点もある 配列のすべてのインデックスはプロパティ名になるが、前述のとおり0から4294967294までの整数のプロパティのみがインデックスである ただしすべての配列はオブジェクトなので配列に対して任意の名前のプロパティを作成できる その場合は配列は特殊な動きをし、必要に応じてlengthプロパティの値を変更する
負数や整数ではない数値を使って配列のインデックスを作成することもできる 数値は文字列に変換され、この文字列がプロパティ名として使われる この場合、プロパティ名は非負数の整数ではないため、配列のインデックスとしてではなく、通常のオブジェクトのプロパティとして扱われる 逆に意図せず非負数の整数で配列のインデックスを作成した場合、オブジェクトのプロパティではなく通常の配列のインデックスを作成することになる(整数値になる浮動小数点値も同様) §7.2にて具体例を挙げる
最後に、配列のインデックスはオブジェクトの特殊なプロパティなので、「配列の範囲外」のエラーは発生しない オブジェクトの存在しないプロパティを取得使用としたときにundefinedが返るのと同じように、配列の存在しないインデックスを取得しようとするとundefinedが返る
7.1 配列の生成
配列を生成するには、配列リテラルを使う方法、反復可能なオブジェクトに対するスプレッド演算子を使う方法、 Array()コンストラクタを使う方法、Array.of()ファクトリメソッドと、Array.from()ファクトリメソッドを使う方法がある
7.1.1 配列リテラル
配列を生成するには[]の中に配列の要素をカンマで区切る配列リテラルを使うのが最も感嘆 配列リテラルには定数だけでなく、任意の式やオブジェクトリテラル、ほかの配列リテラルも記述可能である また、配列リテラルの中に値を記述せずカンマを連続で記述すると配列は疎になる つまり、値を指定しなかった場合、配列の要素は存在せず値を読み出すとundefinedが返る
7.1.2 スプレッド演算子
ES2015以降はスプレッド演算子を使って配列リテラルの中にほかの配列の要素を含めることができる 配列の浅いコピーを作るのに便利
スプレッド演算子は反復可能なオブジェクトに対して機能する(つまりfor/ofループで反復可能なもの 詳細は§12参照) 例えば文字列は反復可能なのでスプレッド演算子を使えば任意の文字列をその文字列の文字を1文字ずつ要素に持つ配列に変換できる Setオブジェクトも反復可能なので配列から重複する要素を削除するには配列をセットに変換しその後スプレッド演算子で配列に戻すのが簡単
7.1.3 Array()コンストラクタ
Array()コンストラクタで呼び出す方法には3種類ある
- 引数無しで呼び出す方法:要素のない空の配列が生成される
- 数値を1つだけ引数にして呼び出す方法:数値は配列の長さになり、指定した長さの要素が空な配列が生成される 0や1などの配列インデックスのプロパティも定義されていない
- 配列に対して、明示的に2つ以上の配列要素、または数値以外の要素を1つだけ指定して呼び出す方法:コンストラクタに対する引数を要素として持つ配列が生成される この場合だと配列リテラルのほうが簡単
7.1.4 Array.of()
Array()コンストラクタでは数値を1つだけ引数にして呼び出すと、その数値は配列の長さになってしまい、数値1つだけの配列を生成することができない ES2015以降Array.of()関数を使うことで、引数の数には関係なく、引数を要素として持つ配列を生成することができる
7.1.5 Array.from()
ES2015にはもう一つ配列を生成するためのファクトリメソッドArray.from()がある 第1引数として反復可能オブジェクトか配列のようなオブジェクトを指定すると、そのオブジェクトの要素を持つ配列を生成する 第2引数には省略可能であるが関数を指定でき、第1引数の各要素に対してその関数を適用する これは配列のmap()メソッドと同じような働きをするが、配列が生成されるときにマッピングを行った方が配列を作成した後に新しい配列にマッピングするよりも効率的である
配列のようなオブジェクトとは数値を持つlengthプロパティを持ち、プロパティ名が整数値である非配列オブジェクトのこと
7.2 配列の要素の読み書き
配列の要素にアクセスするときには[]演算子を使う 負ではない整数値を持つ任意の式を[]の中に書いて配列の要素の読み書きが出来る プロパティ名として0以上4294967295(2^32-1)未満の整数値を使った場合は、配列は自動的にlengthプロパティの値を変更する
7.3 疎な配列
疎な配列とは度々言及している通り要素が0から順に連続して埋まっていない配列のこと 通常配列のlengthプロパティは配列中の要素数を表すが配列が疎の場合、lengthプロパティの値は要素数よりも大きな値になる
以下の方法で疎な配列を生成することができる
- 配列リテラルの中で要素を省略する
- 配列の長さを指定して作成 Array()コンストラクタを使い、配列の長さだけを指定すると指定された長さの疎な配列が生成される
- 配列のインデックスを直接指定して部分的に要素を埋める
- delete演算子を使って配列の特定の要素を削除する(§7.5参照)
疎な配列は密な配列よりも実行速度が遅い代わりにメモリ効率が良くなる また、疎な配列では要素を探す時間は通常のオブジェクトプロパティを探すのと同じくらいである
疎な配列はundefinedの値を持つ通常の配列と扱っても問題ない
7.4 配列の長さ
すべての配列はlengthプロパティを持つ 配列が通常のオブジェクトと異なっている点の一つである 密な配列の場合、lengthプロパティは配列の要素数を表すが、疎な配列の場合、lengthプロパティは配列の要素数ではなく未定義の要素を含めた配列の要素数を表す lengthプロパティは動作を保つため、以下の2つの特殊なふるまいをする
-
lengthプロパティの値を変更すると配列の要素数が変わる
配列の現在のlength以上のインデックスiを指定して配列の要素に値を設定した場合、lengthプロパティの値はi+1に変更される
-
lengthプロパティに現在の値より小さい非負数の整数nを設定した場合、n以上のインデックスを持つ配列の要素は配列から削除される
7.5 配列の要素の追加と削除
配列に要素を追加するには下記の方法がある
- 配列の新しいインデックスに値を設定する
- push()メソッドを使って配列の末尾に要素を追加する(aという配列があった場合、a[a.length]と同じ §7.8参照)
- unshift()メソッドを使って配列の先頭に要素を追加する(§7.8参照)
配列の要素を削除するには下記の方法がある
- delete演算子を使って配列の特定の要素を削除する
- pop()メソッドを使って配列の末尾の要素を削除する(§7.8参照)
- shift()メソッドを使って配列の先頭の要素を削除する(§7.8参照)
他に汎用的なメソッドとしてsplice()メソッドがある splice()メソッドは配列の任意の位置に要素を追加したり削除したり置換したりすることができる splice()メソッドを使うと、lengthプロパティは変更され、必要に応じて配列要素は前後にシフトされる 詳細は§7.8参照
7.6 配列の要素の巡回
ES2015以降は配列(または反復可能なオブジェクト)の各要素をループしたい場合はfor/ofループを使うのが簡単 for/ofについては§5.4.4参照 for/ofループしている際に配列の各要素のインデックスを知りたい場合はentries()メソッドを使う
配列に対して反復処理をする場合forEach()メソッドを使うこともできる これは関数型の手法を提供するメソッドで、配列のforEach()メソッドに対して関数を渡すと、配列の各要素に対してforEach()に渡した関数が呼び出される 詳細は§7.8.1参照 同様にmap()やfilter()メソッドなどもあるがこれらも§7.8.1参照
7.7 多次元配列
JavaScriptでは本当の意味での多次元配列はサポートしていないものの、配列の要素に配列を格納することで多次元配列のようなふるまいを実現することができる 配列の配列要素には[]演算子を2回使えばアクセスできる
7.8 配列のメソッド
配列クラスで定義されているメソッド群について説明する これらのメソッドはメソッドを呼び出した配列そのものを変更するものもあれば、呼び出した配列は変更しないものもある また多くのメソッドは配列を返し、元の配列は変更せず新しい配列を返す場合もあれば、元の配列を変更して元の配列を返す場合もある
配列のメソッドはおおまかに以下のようなものに分類できる
- イテレータメソッド:配列の各要素に対して関数を適用するメソッド
- スタック/キューメソッド:配列の先頭や末尾に要素を追加したり削除したりするメソッド
- サブ配列メソッド:配列の一部を取り出す、置換する、削除する、埋める、コピーするメソッド
- 検索(ソート)メソッド:配列の要素を検索したりソートするメソッド
またArrayクラスの静的メソッドや、そのほか配列を結合したり文字列に変換するメソッドについても説明する
7.8.1 配列イテレータメソッド
配列イテレータメソッドとは配列をループして配列のヨス尾を順番に指定した関数に渡すメソッドのこと 配列の反復処理やマッピング、フィルタリング、テスト、集約を行うときに便利なメソッド
この項で説明するメソッドはすべて第1引数として関数を受け取る この関数は要素ごとまたはいくつかの要素に対して一度ずつ呼び出される 配列がその場合は存在しない要素に対しては関数は呼び出されない 第1引数の関数には多くの場合、配列要素の値とインデックス、配列自身の3つの引数が渡されることが多い 必要なのは配列要素の値だけのことが多いのでその場合は第2引数と第3引数は省略することができる
第2引数は省略可能で、第1引数の関数は第2引数のメソッドとして呼び出される つまり第1引数の関数内のthisは第2引数の値になる
第1引数に指定する関数はほかの場所で定義したものではなく、メソッドを呼び出す式の中でインラインで定義するのが一般的である この時アロー関数(§8.1.3参照)を使うと便利
7.8.1.1 forEach()メソッド
forEach()メソッドは配列の各要素に対して関数を呼び出すメソッドである 前述のとおり、第1引数に関数を指定する その関数を呼び出す際は引数を3つ(要素の値、インデックス、配列自身)渡すことができる 要素の値しか必要でない場合は引数を1つだけ受け取るような関数を既述すればよい
forEach()メソッドにはすべての要素が関数に渡されるまで実行を中止する方法はないので注意
7.8.1.2 map()メソッド Non-Destructive Method
map()メソッドは配列の要素を1つずつ指定した関数に引数として渡し、この関数から返された値を配列に格納しその配列を返す map()メソッドとforEach()メソッドの違いはmap()メソッドは新しい配列を返し、元の配列は変更しない点である そのため、map()メソッドの場合は指定した関数から値を返すようにする必要がある 配列が疎の場合、存在しない要素に対しては関数は呼び出されず、map()メソッドから返される配列も元の配列通り疎になる つまり元の配列と長さが同じになり、同じインデックスの要素が存在しない配列が返される
7.8.1.3 filter()メソッド Non-Destructive Method
filter()メソッドは、配列の要素の部分集合となる配列を返す filter()メソッドに指定した関数が述語(predicate)関数になる この述語関数の戻り値がtrueの場合、その要素は返される配列に含まれる filter()メソッドは元の配列を変更せず、新しい配列を返す 疎の配列の場合、存在しない要素をスキップするため必ず密な配列が返される
7.8.1.4 find()メソッドとfindIndex()メソッド Non-Destructive Method
find()メソッドとfindIndex()メソッドはfileter()メソッドと同じく指定した述語関数がtrueを返す要素を探す ただし、find()メソッドとfindIndex()メソッドは最初に見つかった要素のみを返し、処理を中断する 処理を中断した際にfind()メソッドは見つけた要素を返し、findIndex()メソッドは見つけた要素のインデックスを返す 要素が見つからなかった場合はfind()メソッドはundefinedを返し、findIndex()メソッドは-1を返す
7.8.1.5 every()メソッドとsome()メソッド Non-Destructive Method
every()メソッドとsome()メソッドは配列に対して述語関数を適用しtrueかfalseを返す every()メソッドは記号論理学における全称量化子(∀)に相当し、すべての要素に対して指定した述語関数がtrueを返した場合にtrueを返す some()メソッドは存在量化子(∃)に相当し、配列の少なくとも一つの要素に対して述語関数がtrueを返した場合にtrueを返す また、some()メソッドはすべての要素に対して述語関数がfalseを返した場合にのみfalseを返す
every()メソッドもsome()メソッドも戻り値が確定した時点で処理を中断する 例えばsome()メソッドはtrueを初めて返したときに中断しtrueを返し、falseを返し続けた場合にのみ処理を続ける
数学上の定義と同じように空の配列に対してはevery()メソッドはtrueを返し、some()メソッドはfalseを返す
7.8.1.6 reduce()メソッドとreduceRight()メソッド Non-Destructive Method
reduce()メソッドとreduceRight()メソッドは引数で指定された関数を使い、配列の要素を1つにまとめたものを返す これは関数型プログラミングにおけるinjectやfoldと呼ばれる操作に相当する
reduce()メソッドは配列の先頭から要素を処理し、reduceRight()メソッドは配列の末尾から要素を処理する
reduce()メソッドの第1引数には各要素を処理するための関数、第2引数は省略可能で、第1引数の関数における累積値の初期値を指定する 第2引数の初期値が指定されなかった場合、初期値は配列の最初の要素になり、処理は2番目の要素から始まる 第1引数の関数には4つの引数が渡される
- 累積値(accumulator): 現在の累積値 計算の結果を保持する変数
- 現在の値(current value): 現在処理している配列の要素
- 現在のインデックス(current index): 現在処理している配列の要素のインデックス(省略可能)
- 配列全体(array): reduce()メソッドを呼び出した元の配列(省略可能)
reduce()メソッドもreduceRight()メソッドも簡約化関数が呼び出されるときのthisの値を指定できない 簡約化関数をある特定のオブジェクトのメソッドとして呼び出したい場合はFunction.bind()メソッドを使う(8.7.5参照)
7.8.2 flat()メソッドとflatMap()メソッドによる配列のフラット化 Non-Destructive Method
ES2019よりflat()メソッドが追加された flat()メソッドは、このメソッドを呼び出した配列と同じ要素を持つ新しい配列を作成し、その配列を返す 新しい配列を作成する際、元の配列の各要素をフラット化(展開)されて返す
引数を指定しなかった場合、flat()は入れ子の1階層分だけ展開する つまり元の配列の要素のうち、その要素自身が配列の場合は展開されるが、その配列の要素が配列の場合は展開されない 展開する階層を変更したい場合、flat()メソッドの引数を指定することで展開する階層を指定できる
flatMap()メソッドはmap()メソッドとflat()メソッドを組み合わせたものである ただし、返される配列が自動的に展開される点が異なる a.flatMap(f)はa.map(f).flat()と同じ結果を返すがflatMap()メソッドの方が効率的である flatMap()は、map()メソッドを汎化して入力配列の各要素に対して出力配列の任意の数の要素にマップできるようにしたものと考えてもよい 他にはflatMap()を使えば入力要素を空の配列にマップすることもできる
7.8.3 concat()メソッドによる配列の結合 Non-Destructive Method
concat()メソッドは、concat()メソッドを呼び出した配列の要素の後ろに、引数で指定された配列の要素を追加した新しい配列を生成して返す 引数のうちいずれかが配列である場合、配列のまま追加するのではなく、配列の要素を展開して配列に追加する(入れ子の配列は展開されない) ただしconcat()メソッドは配列の配列を再帰的に展開することはない concat()は場合によって負荷が大きい処理のため、元の配列を操作するpush()やsplice()メソッドを使うことも候補にいれるとよい
7.8.4 push()メソッド、pop()メソッド、shift()メソッド、unshift()メソッドによるスタック/キュー Destructive Method
push()メソッドとpop()メソッドを使用するとスタックと同じやり方で配列を操作できる push()メソッドは配列の最後に1個または複数の要素を追加し、追加した後の配列の長さを返す push()メソッドでは引数に配列を指定しても配列を展開せず、その配列を要素として追加する pop()メソッドは配列の最後の要素を削除してその削除した要素を返す
unshift()メソッドとshift()メソッドを使用すると配列の先頭の位置で要素の出し入れをする unshift()メソッドは配列の先頭に1個または複数の要素を追加し、既存の配列要素をより大きいインデックス番号の方向へシフトさせた後、追加した後の配列の長さを返す shift()メソッドは配列の先頭の要素を削除して空になった場所へ後続の要素をずらし、その削除した要素を返す
unshift()とshift()を使ってスタックを実装することは出来るが、push()とpop()を使う方が効率的である(シフト操作が入るため) ただし、push()とshift()でキュー構造を作ることはできる
7.8.5 slice()メソッド、splice()メソッド、fill()メソッド、copyWithin()メソッドによるサブ配列操作
配列には連続する領域や配列の「サブ配列(スライス)」を処理するメソッドが数多く定義されている ここではスライスの抽出、置換、要素の設定、コピーを行うメソッドについて説明する
7.8.5.1 slice()メソッド Non-Destructive Method
slice()メソッドは指定された配列のサブ配列(スライス)を返す 返すスライス配列の先頭を第1引数で指定し、第2引数でスライス配列の末尾を指定する(第2引数は省略可能) スライス配列には第1引数で指定された要素から第2引数で指定された要素の1つ前までの要素が格納される
指定した引数のどちらかが負数の場合、配列の最後からの相対位置で配列要素が指定されたものと解釈される 例えば-1をしてすると配列の最後の要素が指定されたものと解釈される
なおslice()メソッドは元の配列を変更せず、新しい配列を返す
7.8.5.2 splice()メソッド Destructive Method
splice()メソッドは、配列に要素を挿入したり配列から要素を削除したりする汎用的なメソッドであり、削除した要素を返す slice()メソッドやconcat()メソッドとは異なり、splice()メソッドは元の配列を変更する splice()メソッドは要素の挿入や削除を別々に行うだけではなく、挿入と削除を同時に実行することもできる 挿入や削除が行われた後、連続した密の配列になるように要素がシフトされて必要に応じてインデックスが増加/減少する
削除する場合は第1引数に挿入や削除を開始する位置を指定し、第2引数に削除する要素の個数を指定する(第2引数は省略可能) 第2引数を省略した場合は第1引数で指定した位置から最後までの要素が削除される
挿入する場合は第3引数以降が挿入する要素となる 第1引数や第2引数は通常通り削除の動作を行うので、ただ挿入するだけの場合は第2引数に0を指定する
splice()メソッドはconcat()メソッドとは違い、配列要素を展開しないでそのまま挿入する
7.8.5.3 fill()メソッド Destructive Method
fill()メソッドは配列要素または配列のスライスを指定した値に設定する fill()メソッドは元の配列を変更し、変更した配列を返す 第1引数には配列の要素に設定する値を指定する 第2引数は省略可能で、開始位置を指定できる 省略した場合はインデックス0から始まる 第3引数も省略可能で、終了位置を指定できる ただし指定したインデックスの要素は設定されない 省略した場合は配列の長さまでとなる 第2引数と第3引数の値が負数の場合、配列の最後からの相対位置で指定されたものと解釈される
7.8.5.4 copyWithin()メソッド Destructive Method
copyWithin()メソッドは配列のスライスを指定した位置にコピーする copyWithin()メソッドは元の配列を変更し、変更した配列を返す ただし配列の長さは変更しない 第1引数にはコピーする配列のスライスの内の最初の要素のコピー先となるインデックスを指定する 第2引数は省略可能で、コピーを開始するインデックスを指定する 省略した場合はインデックス0から始まる 第3引数も省略可能で、コピーを終了するインデックスを指定する 省略した場合は配列の長さまでとなる 引数として負数を渡した場合は配列の最後からの相対位置で指定されたものと解釈される
copyWithin()メソッドは高速処理が可能で、型付き配列に使うと便利である copyWithin()メソッドはC言語の標準ライブラリのmemmove()関数を元にしている なお、コピー元とコピー先の領域が重なっていてもコピーは問題なく処理される
7.8.6 配列の検索メソッドとソートメソッド
配列には文字列と同じようにindexOf()メソッドやlastIndexOf()メソッド、includes()メソッドが実装されている また、配列の要素を並べ替えるsort()メソッドやreverse()メソッドもある この項では上記メソッドについて説明する
7.8.6.1 indexOf()メソッドとlastIndexOf()メソッド Non-Destructive Method
indexOf()メソッドとlastIndexOf()メソッドは、配列中から指定した値を持つ要素を探し、要素が見つかったら最初に見つかったインデックスを返す 見つからなかった場合-1を返す indexOf()メソッドは配列の先頭から探索を行い、lastIndexOf()メソッドは配列の末尾から探索を行う
両者とも第1引数に探す値を指定する 第2引数は省略可能で、探索を開始するインデックスを指定する 省略した場合はindexOf()メソッドは0、lastIndexOf()メソッドは配列の最後の要素のインデックスから探索を開始する 引数に負数を指定した場合は配列の最後からの相対位置で指定されたものと解釈される
indexOf()メソッドとlastIndexOf()メソッドは引数と配列の要素を比較する際に===演算子を使う そのためNaN値を探すことができない(NaN値は一律で-1を返す) 配列の要素がプリミティブ値ではなくオブジェクトの場合は引数と要素が同じオブジェクトを参照しているかどうかを調べる オブジェクトの内容で比較したい場合はfind()メソッドを使う必要がある
7.8.6.2 includes()メソッド Non-Destructive Method
ES2016よりincludes()メソッドが追加された includes()メソッドは引数を1つ取り、引数で指定した値が配列に含まれている場合はtrueを返し、含まれていない場合はfalseを返す 多くの要素に対して処理を行いたい場合は配列ではなくSetオブジェクトを使うとよい indexOf()メソッドでは===演算子と同じアルゴリズムで比較を行い、NaN値に対してはNaN値を含めてすべて異なると判定するのに対し、 includes()メソッドではNaN値はNaN値と等しいと判断する つまりindexOf()メソッドではNaN値を調べることができないが、includes()メソッドでは調べることができる
7.8.6.3 sort()メソッド Destructive Method
sort()メソッドは配列の要素を並び替えするのに使用される sort()メソッドは新しい配列を生成するのではなく既存の配列をソートし、ソートした配列を返す
引数を指定しないでsort()メソッドを呼び出すと、アルファベット順に配列要素をソートする その際、必要に応じて要素を文字列に変換して比較する 配列の要素にundefinedが含まれる場合は、その要素は配列の最後に配置される
アルファベット順以外でソートしたい場合は、sort()メソッドの引数に比較関数を指定する この関数は2つの引数を取り、第1引数を第2引数より前にしたい場合は、関数から返す値をゼロより小さくする必要がある 逆に第1引数を第2引数より後ろにしたい場合は、関数から返す値をゼロより大きくする必要がある 2つの引数が等しい場合(順序関係がない場合)は、関数から返す値はゼロでなければならない
7.8.6.4 reverse()メソッド Destructive Method
reverse()メソッドは配列の要素を逆順にするときに使用される reverse()メソッドは新しい配列を生成するのではなく、既存の配列を逆順にし、逆順にした配列を返す
7.8.7 配列から文字列への変換 Non-Destructive Method
Arrayクラスには配列を文字列に変換するメソッドが3つ用意されていて、一般的にはログやエラーメッセージを作成するときに使う (配列の内容を後で再利用できるような形式でテキストにしたい場合はJSON.stringify()メソッドを使ってシリアライズするのがよい)
1つめのjoin()メソッドは配列のすべての要素を文字列に変換して連結し、連結した文字列を返す 各要素を区切るための文字を指定することも可能で、特に指定しない場合はカンマが区切り文字として使われる 逆に文字列を分離して配列を生成するメソッドとしてsplit()メソッドがある
2つめのtoString()メソッドはjoin()メソッドの引数を省略した場合と同じように、配列のすべての要素を文字列に変換してカンマで区切り、連結した文字列を返す toString()メソッドはArray.prototype.toString()メソッドのエイリアスである
3つめのtoLocaleString()メソッドはtoString()メソッドと同じように、配列のすべての要素を文字列に変換してカンマで区切り、連結した文字列を返す ただし、各要素を文字列に変換する際に個々の要素を文字列に変換し、それをロケール固有の区切り文字で区切ったリストを出力する 区切り文字が度の文字になるのかは処理系に依存する
7.8.8 配列の静的関数
Arrayクラスにはオブジェクトに対して実行するのではなく、Arrayコンストラクタから呼び出す静的関数が3つ定義されている そのうち2つがArray.of()メソッドとArray.from()メソッドでありそれぞれ§7.1.4と§7.1.5で説明した 残りの1つがArray.isArray()メソッドでありこのメソッドは引数に指定した未知の値が配列かどうかを判定する
7.9 配列のようなオブジェクト
以上をまとめるとJavaScriptの配列には通常のオブジェクトとは異なる以下のような特性がある
- 配列に新しい要素が追加されると自動的にlengthプロパティが更新される
- lengthプロパティに現在の長さより小さな値を設定することで配列を縮められる
- 配列はArray.prototypeから便利なメソッドを継承する
- Array.isArray()は配列に対してtrueを返す
上記に述べた特性は配列固有の特徴だが、ほかにもこの特徴をもつオブジェクトが存在する 例えば通常のオブジェクトに対してlengthプロパティを設定し、対応する非負数の整数値のプロパティを持つようにしたものを配列として扱ってもよい ただしこの配列のようなオブジェクトに対して、通常の配列のメソッドは直接呼び出しが出来ず、またlengthプロパティも通常の配列のような振る舞いをしない
しかし仮に通常の配列に対して配列要素を調べるコードやアルゴリズムがあったとして、それを配列のようなオブジェクトに対しても使用できることが多くある
クライアントJavaScriptではdocument.querySelectorAll()などいくつかのメソッドが配列のようなオブジェクトを返す
7.10 配列としての文字列
JavaScriptの文字列はUTF-16のUnicode文字の読み出し専用の配列のようにふるまう つまり、個々の文字にアクセスする際にcharAt()メソッドの代わりに[]を使うことができる
ただし、配列ではないのでtypeof演算子で文字列を調べると"string"が返され、Array.isArray()メソッドで調べるとfalseが返される
ただ、配列のようにふるまうので、文字列に対してArray.prototypeのメソッドを使うことができる その際、文字列を含むプリミティブ値は不変であるため、push()やsort()などの破壊的なメソッドは使えない
7.11 まとめ
最後に配列のメソッドを破壊的・非破壊的メソッドにまとめる
| 分類 | メソッド名 | 概要 |
|---|---|---|
| 破壊的 | push | 配列の末尾に要素を追加し、変更後の配列の長さを返します。 |
| pop | 配列の末尾の要素を削除し、その削除された要素を返します。 | |
| shift | 配列の先頭の要素を削除し、その削除された要素を返します。 | |
| unshift | 配列の先頭に要素を追加し、変更後の配列の長さを返します。 | |
| splice | 配列の指定位置に要素を追加・削除します。元の配列を変更します。 | |
| sort | 配列をソートし、元の配列を変更します。 | |
| reverse | 配列の要素を逆順に並び替え、元の配列を変更します。 | |
| copyWithin | 配列の指定範囲をコピーして別の位置に上書きします(元の配列を変更)。 | |
| fill | 配列内の指定範囲を静的な値で埋めます(元の配列を変更)。 | |
| forEach | 配列の各要素に対してコールバック関数を適用します。 | |
| 非破壊的 | concat | 2つ以上の配列を結合し、新しい配列を返します。 |
| slice | 配列の指定範囲を抽出し、新しい配列を返します。 | |
| map | 各要素に対してコールバック関数を適用した結果の新しい配列を返します。 | |
| filter | 条件を満たす要素のみを含む新しい配列を返します。 | |
| reduce | 配列を1つの値に畳み込みます(元の配列は変更されません)。 | |
| reduceRight | 配列を右から左に畳み込みます(元の配列は変更されません)。 | |
| find | 条件を満たす最初の要素を返します(元の配列は変更されません)。 | |
| findIndex | 条件を満たす最初の要素のインデックスを返します。 | |
| includes | 指定された値が配列に含まれているかを真偽値で返します。 | |
| indexOf | 指定された値の最初のインデックスを返します。 | |
| lastIndexOf | 指定された値の最後のインデックスを返します。 | |
| every | 全ての要素が条件を満たすかどうかを真偽値で返します。 | |
| some | 少なくとも1つの要素が条件を満たすかを真偽値で返します。 | |
| join | 配列の全要素を文字列として結合し、1つの文字列を返します。 | |
| flat | ネストされた配列を指定された深さまで展開した新しい配列を返します。 | |
| flatMap | mapとflatを組み合わせた新しい配列を返します。 | |
| toString | 配列を文字列に変換して返します。 | |
| toReversed | 配列を逆順にした新しい配列を返します(元の配列は変更されません)。 | |
| toSorted | 配列をソートした新しい配列を返します(元の配列は変更されません)。 | |
| toSpliced | 配列を指定範囲で操作した新しい配列を返します(元の配列は変更されません)。 | |
| with | 指定したインデックスの要素を置き換えた新しい配列を返します。 |