LoginSignup
0
0

More than 3 years have passed since last update.

【javascript】配列メソッド

Last updated at Posted at 2020-06-26

こちらの記事は以下の書籍を参考に執筆しました

Array.fromを使って配列を作成

数値の平均を求める関数お作成しているとして、以下のような関数の定義はうまく実装されません。

function avg() {
  const sum = arguments.reduce(function(a, b) {
    return a + b;
  })
  return sum / arguments.length;
}

出典:入門JavaScriptプログラミング

なぜならargumentsオブジェクトは配列ではなく、配列のようなオブジェクトだからです。。
"arguments.reduce is not a function"というエラーは、argumentsオブジェクトを配列に変換する必要があるということです。

配列のようなオブジェクトを配列に変換するにはArray.prototypesliceメソッドを適応させます。
sliceを引数無しで呼び出すと、配列のシャローコピーを作成します。これを配列のようなオブジェクトに適応しても、配列が作成されます。
またArray.prototype.applyでもうまくいきます。

配列のようなオブジェクト
配列でないものの、lengthプロパティを持ち、添字によるアクセスができ、forループで処理もできるオブジェクトのこと。

Array.prototype.slice.call(arrayLikeObject);

//または
[].slice.call(arrayLikeObject);

出典:入門JavaScriptプログラミング

これを使用して先の関数を修正します。

function avg() {
  const args=[].slice.apply(arguments);
  const sum = args.reduce(function(a, b) {
    return a + b;
  })
  return sum / arguments.length;
}

出典:入門JavaScriptプログラミング

以下はArray.fromを使用してバージョンです。


function avg() {
  const args=Array.from(arguments);
  const sum = args.reduce(function(a, b) {
    return a + b;
  })
  return sum / arguments.length;
}

出典:入門JavaScriptプログラミング

Array.fromは配列のようなオブジェクトを配列に変換します。

Array.fromdocument.querySelectorAllとの組み合わせ

document.querySelectorAllのオブジェクト型はNodeListであり、配列ではありません。

Array.fromはlengthプロパティを持つオブジェクトであれば、どのオブジェクトでもうまくいきます。
配列にしたい対象がlengthプロパティを持ってさえいれば配列に変換できるということです。

Array.from({length:50})

出典:入門JavaScriptプログラミング

これによりnew Array(50)と同じ新しい配列が作成されます。
これは長さが50の配列です。

Array.ofを使って配列を作成

以下のコードを執行するとどうなるでしょう。

let a=new Array(1,2,3)
let b=new Array(1,2)
let c=new Array(1)

出典:入門JavaScriptプログラミング

aとbは普通の配列が作成されるが、cの結果はemptyとなり、1つの値を持った配列を作成できません。
これはArrayのコンストラクタの振る舞いです。
これを回避する方法としてArray.ofファクトリメソッドを使用します。

let a=Array.of(1,2,3)
let b=Array.of(1,2)
let c=Array.of(1)

出典:入門JavaScriptプログラミング

こうすることで1つの値を持つ配列を作成できます。

「そんなことしなくても配列リテラルをつ開けばよいのでは?」と思うかもしれないです。

let a=[1,2,3]
let b=[1,2]
let c=[1]

出典:入門JavaScriptプログラミング

しかしこれがうまく行かない状況があります。
その一つは配列のサブクラスを使用しているときです。
AwesomeArrayというArrayのサブクラスを使用しているとします。
するとAwesomeArrayはnew AwesomeArray(1)が使えません。

更に配列リテラルも使用できません。
配列リテラルを使用するとAwesomeArrayではなくArrayのインスタンスになってしまうからです。

しかしArray.ofは使用できるため、1つの値に1つだけ含まれたAwesomeArrayのインスタンスが返されます。

Array.prototype.fillを使って配列を作成

ここでは三目並べゲームを作っていきます。
具体的な構成は以下です。
- 9個のマスは長さ9の配列を使用
- マスにおけるのは"x"と"o"、マスは空("")で表現

配列をboardとするとこのように初期化できる。

const board = new Array(9).map(function(i) {
  return ' ';
})

出典:入門JavaScriptプログラミング

map() メソッドは、与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列を生成します。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map

new Array(9)で9この値を持つ配列を初期化すると、すべての値がundefinedになるので、mapでundefined値をそれぞれスペースに変換します。
しかしこの方法はうまくいきません。

new Array(9)を実行すると実際には9個のundefinedが追加されるのではなく、lengthプロパティに9が設定された新しい配列が作成されるだけだからです。

どういうことかというと、例えば['a','b','c']という配列を作成したとすると内部ではこうなっています。

{
  length:3
  0:'a',
  1:'b',
  2:'c',
}

出典:入門JavaScriptプログラミング

new Array(9)を実行すると配列の内部では下記のようになっていると思ってしまいます。

{
  length:9
  0:undefined,
  1:undefined,
  2:undefined,
  3:undefined,
  4:undefined,
  5:undefined,
  6:undefined,
  7:undefined,
  8:undefined,  
}

出典:入門JavaScriptプログラミング

しかし実際にはこうです。

{
  length:9
}

出典:入門JavaScriptプログラミング

lengthプロパティが設定されているだけで、値は含まれていません。
欠けている値は(hole)と呼ばれます。
mapには対応しないのはこれが原因です。

配列に特定の値を設定するにはfillを使用します。

const board = new Array(9).fill(' ');

出典:入門JavaScriptプログラミング

Array.prototype.includeを使って配列を検索する

String.prototype.includeと同様に配列にもincludeが同じように機能します。

Array.prototype.includeメソッドは配列のいずれかのインデックス位置に含まれている値が、指定された値を同じかどうかをチェックします。
これまではindexOfが使用されていました。
indexOfは結果に-1が含まれていた場合の比較を忘れてしまうバグが有りましたが、includeはブーリアンを返します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0