1
0

More than 1 year has passed since last update.

配列風(ArrayLike)オブジェクトってなんだよ、'風'ってよぉ~

Last updated at Posted at 2022-10-22

ググったら秒で分かった(わかってなかった)

関数の引数であるargumentsNodeListが該当するみたい。
Arrayのメソッドを継承しているわけでないから、配列として操作する時にひと手間必要ってわけね。
変換もできるし、'風'と名乗っていることも許せる。

「配列風」とは、 arguments が length プロパティと 0 から始まる添字のプロパティを持っているものの、 Array の組込みメソッド、例えば forEach() や map() を持っていないということです
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/arguments

ご指摘いただき追記:
ES2022に配列風オブジェクトの正式な定義が載っており、Arrayが満たしているiterableとArrayLikeを混同しておりました。

iterableとArrayLikeの解説

なぜスプレッド構文を使っていたかの謎が解けた

いちいちスプレッド構文を使って配列に格納し直しているコードを見かけるけど、Arrayのメソッドを使うためだったとは...
理由を調べていなかったことに反省。
どうりで予測変換でmapメソッドとか出ないわけだ。

ArrayLikeは Array.from() で配列(new Array)に変換可能ですが、SpreadElementでは展開できません

→スプレッド構文を利用した配列変換とArray.from()による配列変換は明確に違いがある。

// 例のため実用性のあるコードではない
const nodeList = document.querySelectorAll('.aaa, .bbb');
const func = () => [...nodeList].map(t => t);

スプレッド構文以外にもargumentsを配列として扱う方法はある

argumentsの場合は、基本的にslice()やArray.from()でシャローコピーして配列生成を行う
iterableでなく、ArrayLikeのみ満たしているオブジェクトの場合はスプレッド構文で変換できず、Array.from()による変換が正規の方法となります

Arrayへの変換
const hello = function (x, y) {
  // arguments.slice ←Arrayのメソッドは使えないがインデックスで参照はできる
  return [arguments[0], arguments[1]];
};

// 配列風オブジェクトであるargumentsでArrayのsliceメソッドを利用
const helloArgumentsSlice = function (x, y) {
  // 配列のsliceメソッドを代入
  const slice = Array.prototype.slice;
  // call()で呼び出して引数として渡せば配列として生成可能
  return slice.call(arguments);
};

// 配列風オブジェクトであるargumentsでArrayのsliceメソッドを利用
const helloArgumentsSliceSugar = function (x, y) {
  // Array.prototype.call()の糖衣構文
  return [].slice.call(arguments);
};

// 配列にしてslice()呼ぶ
const helloArgumentsSliceSugar2 = function (x, y) {
  // スプレッド構文で配列として生成(ES2015以降)
  return [...arguments].slice();
};

// 配列にしてslice()呼ぶ
const helloArgumentsSliceSugar3 = function (x, y) {
  // この変換のみ配列として生成(ES2015以降)
  return Array.from(arguments).slice();
};

ArrayLikeオブジェクトの場合はスプレッド構文を使った変換だとエラーになりました。

スプレッド構文だとエラー
const arrayLikeConvertArray = function () {
  // arrayLikeオブジェクト追記
  const arrayLike = { 0: 1, 1: 2, length: 2 };
  console.log("Array.from", Array.from(arrayLike));
  console.log("Array.prototype.slice", Array.prototype.slice.call(arrayLike));
  console.log("[].slice", [].slice.call(arrayLike));
  // これは変換できずにTypeError
  // console.log([...arrayLike].slice());
  return "ArrayLikeの変換はconsoleを参照してください";
};

出力結果の確認などのコード全行はこちら

参考

1
0
2

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
1
0