1. ホーム
  2. javascript

[解決済み] JavaScriptで[].forEach.call()は何をするのですか?

2022-05-30 06:57:02

質問

コードのいくつかのスニペットを見ていたところ、空の配列に適用される forEach でノード リスト上で関数を呼び出す複数の要素を見つけました。

たとえば、私は次のようなものを持っています。

[].forEach.call( document.querySelectorAll('a'), function(el) {
   // whatever with the current node
});

と書いているのですが、どのように動作するのか理解できません。どなたか、forEachの前の空の配列の動作と、どのように call がどのように機能するのか説明できますか?

どのように解決するのですか?

[] は配列です。

この配列は全く使われません。

ページに置かれているのは、配列を使うことで配列のプロトタイプにアクセスできるためで、例えば .forEach .

と打つより早いです。 Array.prototype.forEach.call(...);

次は forEach は関数を入力とする関数です...

[1,2,3].forEach(function (num) { console.log(num); });

...そして、各要素に対して this (ここで this は配列のようなもので、その中に length のようにその部分にアクセスすることができます。 this[1] のように)3つのものを渡します。

  1. 配列の要素
  2. 要素のインデックス (3番目の要素なら 2 )
  3. 配列への参照

最後に .call は関数が持つプロトタイプです(他の関数に呼び出される関数です)。

.call はその最初の引数を取り this を通常の関数内で call を最初の引数として渡します ( undefined または nullwindow を使用します。quot;strict-mode")であれば、あなたが渡したものが使用されます。残りの引数は、元の関数に渡されます。

[1, 2, 3].forEach.call(["a", "b", "c"], function (item, i, arr) {
    console.log(i + ": " + item);
});
// 0: "a"
// 1: "b"
// 2: "c"

したがって、あなたは素早く呼び出す方法を作成し forEach 関数を呼び出す手っ取り早い方法を作っているわけで、そのために this を空の配列からすべての <a> タグのリストに変換し、それぞれの <a> の順で、提供された関数を呼び出していることになります。

EDIT

論理的な結論/後始末

この解決策はハック的で見苦しいので、関数型プログラミングの試みは破棄し、毎回、手動でインラインループに固執することを提案する記事へのリンクが以下にあります。

私が言いたいのは .forEach は対応するものに比べて、あまり役に立ちません。 .map(transformer) , .filter(predicate) , .reduce(combiner, initialValue) のいずれかにアクセスしながら、(配列ではなく)外界をn回変更したい場合、この方法はまだ役に立ちます。 arr[i] または i .

では、Mottoは明らかに才能と知識のある人物であり、私は自分が何をしているか/どこへ行くかを知っていると想像したいのですが(今も昔も... ...他の時は頭を使って学んでいます)、この格差にはどう対処すればいいのでしょうか?

その答えは実にシンプルで、ボブおじさんもクロックフォード卿も、その見落としのために顔面蒼白になるようなものです。

クリーンアップする .

function toArray (arrLike) { // or asArray(), or array(), or *whatever*
  return [].slice.call(arrLike);
}

var checked = toArray(checkboxes).filter(isChecked);
checked.forEach(listValues);

さて、もしあなたが自分でこれをする必要があるかどうか疑問に思っているなら、答えは「いいえ」かもしれません...。

この正確なことは、... ...最近の高次機能を持つすべての(?)ライブラリによって行われています。

もしあなたがlodashやunderscore、あるいはjQueryを使っているなら、それらはすべて要素のセットを取って、あるアクションをn回実行する方法を持っているはずです。

そのようなものを使っていないのであれば、是非とも自分で書いてください。

lib.array = (arrLike, start, end) => [].slice.call(arrLike, start, end);
lib.extend = function (subject) {
  var others = lib.array(arguments, 1);
  return others.reduce(appendKeys, subject);
};

ES6(ES2015)以降のアップデートについて

だけでなく slice( ) / array( ) /しかし、比較的近い将来の ES6+ ブラウザで操作したり、今日 Babel で "transpiling" する余裕がある人々にとっては、この種のものを不要にする言語機能が組み込まれています。

function countArgs (...allArgs) {
  return allArgs.length;
}

function logArgs (...allArgs) {
  return allArgs.forEach(arg => console.log(arg));
}

function extend (subject, ...others) { /* return ... */ }


var nodeArray = [ ...nodeList1, ...nodeList2 ];

超きれいで、とても便利です。

を調べてみてください。 休む そして 拡散 BabelJSのサイトで試してみてください。技術的に問題なければ、Babelとビルドステップで本番環境で使用してください。


非配列から配列への変換を使用できない正当な理由はありません... ...ただ、何もしないことでコードを混乱させないようにしてください。 しかし のみで、同じ醜い行をどこにでも貼り付けるような、あなたのコードを混乱させるようなことはしないでください。