web-dev-qa-db-ja.com

javascript forEachメソッドにはどのような用途がありますか(マップではできません)。

私がmapとforeachで見る唯一の違いは、mapが配列を返し、forEachが返さないことです。ただし、forEachメソッドの最後の行 "func.call(scope, this[i], i, this);"も理解していません。たとえば、「this」と「scope」は同じオブジェクトを参照せず、this[i]iは現在の値を参照しませんループ?

別の投稿で、誰かが「リストの各要素に基づいて何かをしたいときにforEachを使用してください。たとえば、ページに何かを追加しているかもしれません。本質的に、 「副作用」が必要です副作用の意味がわかりません.

Array.prototype.map = function(fnc) {
    var a = new Array(this.length);
    for (var i = 0; i < this.length; i++) {
        a[i] = fnc(this[i]);
    }
    return a;
}

Array.prototype.forEach = function(func, scope) { 
    scope = scope || this; 
    for (var i = 0, l = this.length; i < l; i++) {
        func.call(scope, this[i], i, this); 
    } 
}

最後に、javascriptでこれらのメソッドを実際に使用する方法はありますか(データベースを更新していないため)。

alert([1,2,3,4].map(function(x){ return x + 1})); //this is the only example I ever see of map in javascript.

返信いただきありがとうございます。

87
JohnMerlino

あなたの例のmapforEachの本質的な違いは、forEachは元の配列要素に対して動作するのに対し、mapは結果として新しい配列を明示的に返すことです。 。

forEachを使用すると、元の配列の各要素を使用して(およびオプションで変更を使用して)アクションを実行します。 forEachメソッドは、各要素に指定した関数を実行しますが、何も返しません(undefined)。一方、mapは配列を調べ、各要素に関数を適用し、結果を新しい配列として出力します

forEachの「副作用」は、元の配列が変更されることです。 mapによる「副作用なし」は、慣用的な使用法では、元の配列要素がnot変更されたことを意味します。新しい配列は、元の配列の各要素の1対1マッピングです。マッピング変換は、提供された関数です。

データベースが含まれていないという事実は、データ構造を操作する必要がないという意味ではありません。これは、結局のところ、どの言語でもプログラミングの本質の1つです。最後の質問に関しては、配列には数字だけでなく、オブジェクト、文字列、関数などを含めることができます。

91
Ken Redler

2つの方法の主な違いは概念とスタイルです:何かをしたいときにforEachを使用しますtoまたはwith配列の各要素( "with"を行うことは、引用した投稿が "副作用"を意味するものだと思います)、コピーしたい場合はmapを使用しますそして、(元を変更せずに)配列の各要素を変換します

mapforEachの両方が配列内の各項目で関数を呼び出し、その関数はユーザー定義であるため、一方ではできても他方ではできないことはほとんどありません。いですが、mapを使用して、配列をインプレースで変更したり、配列要素で何かをしたりできます。

var a = [{ val: 1 }, { val: 2 }, { val: 3 }];
a.map(function(el) {
    el.val++; // modify element in-place
    alert(el.val); // do something with each element
});
// a now contains [{ val: 2 }, { val: 3 }, { val: 4 }]

forEachを使用する意図については、より明確で明確です。

var a = [{ val: 1 }, { val: 2 }, { val: 3 }];
a.forEach(function(el) { 
    el.val++;
    alert(el.val);
});

特に、現実の世界では通常そうであるように、elは人間が読むことができる便利な変数です。

cats.forEach(function(cat) { 
    cat.meow(); // nicer than cats[x].meow()
});

同様に、forEachを使用して新しい配列を簡単に作成できます。

var a = [1,2,3],
    b = [];
a.forEach(function(el) { 
    b.Push(el+1); 
});
// b is now [2,3,4], a is unchanged

ただし、mapを使用するとよりクリーンになります。

var a = [1,2,3],
    b = a.map(function(el) { 
        return el+1; 
    });

また、mapは新しい配列を作成するため、特に大規模な配列の場合に反復が必要な場合、少なくともパフォーマンス/メモリヒットが発生する可能性が高いことに注意してください- http://jsperf.comを参照/ map-foreach

これらの関数を使用する理由については、JavaScriptで配列操作を行う必要があるときはいつでも役立ちます(ブラウザ環境でJavaScriptについて話しているだけでも)、ほとんどの場合コードに手で書き留めていない配列にアクセスしています。ページ上のDOM要素の配列、またはAJAXリクエストからプルされたデータ、またはユーザーがフォームに入力したデータを処理している可能性があります。外部APIから、mapを使用してデータを目的の形式に変換し、forEachを使用して新しい配列を反復処理してユーザーに表示します。

66
nrabinowitz

投票された回答(Ken Redlerから)は誤解を招きます。

コンピューターサイエンスの副作用は、関数/メソッドのプロパティがグローバル状態を変更することを意味します [wiki] 。狭い意味では、これには引数からではなく、グローバル状態からの読み取りも含まれます。命令型またはOOプログラミングでは、ほとんどの場合、副作用が発生します。おそらく、気付かないうちにそれを使用している可能性があります。

forEachmapの重要な違いは、mapがメモリを割り当てて戻り値を格納するのに対し、forEachはそれを破棄することです。詳細については、 emca spec を参照してください。

副作用が必要なときにforEachが使用されると言う理由は、forEachの戻り値が常にundefinedであるためです。副作用がない(グローバルステートを変更しない)場合、関数はCPU時間を無駄にしています。最適化コンパイラは、このコードブロックを削除し、最終値(undefined)に置き換えます。

ところで、JavaScriptには副作用に対する制限がないことに注意してください。 map内の元の配列を引き続き変更できます。

var a = [1,2,3]; //original
var b = a.map( function(x,i){a[i] = 2*x; return x+1} );
console.log("modified=%j\nnew array=%j",a,b);
// output:
// modified=[2,4,6]
// new array=[2,3,4]
14
Jack Tang

これは、予想外の答えがある美しい質問です。

以下は Array.prototype.map()の公式の説明 に基づいています。

nothingがあり、forEach()はできますが、map()はできません。つまり、map()は、forEach()strict super-setです。

map()は通常、新しい配列を作成するために使用されますが、現在の配列を変更するためにalsoも使用できます。以下に例を示します。

_var a = [0, 1, 2, 3, 4], mapped = null;
mapped = a.map(function (x) { a[x] = x*x*x; return x*x; });
console.log(mapped); // logs [0, 1, 4, 9, 16]  As expected, these are squares.
console.log(a); // logs [0, 1, 8, 27, 64] These are cubes of the original array!!
_

上記の例では、aは、_a[i] === i_が_i < a.length_になるように便利に設定されていました。それでも、それはmap()の力、特に呼び出される配列を変更する能力を示しています。

注1:
公式の説明は、map()が呼び出される配列の長さlengthを変更する可能性があることを暗示しています!ただし、これを行う(正当な)理由がわかりません。

注2:
_map()マップはforEach()のスーパーセットですが、特定の配列を変更したい場合はforEach()を使用する必要があります。これにより、意図が明確になります。

これが役に立てば幸いです。

6
Sumukh Barve

mapであるかのようにforEachを使用できます。

ただし、必要以上のことを行います。

scopeは任意のオブジェクトにすることができます。必ずしもthisではありません。

mapおよびforEachの実際の使用があるかどうか、およびforまたはwhileループの実際の使用があるかどうかを尋ねます。

3
wombleton

上記の質問はすべて正しいですが、私は間違いなく別の区別をします。 mapforEachの使用は意図を暗示することができます。

何らかの方法で既存のデータを単純に変換するときに(ただし、元のデータが変更されていないことを確認したい場合)、mapを使用するのが好きです。

コレクションを適切に変更するときは、forEachを使用するのが好きです。

例えば、

var b = [{ val: 1 }, { val: 2 }, { val: 3 }];
var c = b.map(function(el) {
    return { val: el.val + 1 }; // modify element in-place
});
console.log(b);
//  [{ val: 1 }, { val: 2 }, { val: 3 }]
console.log(c);
//  [{ val: 3 }, { val: 4 }, { val: 5 }]

私の経験則では、mapを実行するときは、単にソースリストの各要素に対して返される新しいオブジェクト/値を作成し、returningで単に操作を実行するのではなく、各要素。

既存のリストを実際に変更する必要がない限り、その場でリストを変更することは実際には意味がなく、機能的/不変のプログラミングスタイルにより適しています。

1
maschwenk

再び、私はネクロマンサーが5年前に尋ねられた質問に回答を追加しているように感じます(幸いなことに、最近の活動があるので、死者を邪魔するのは私だけではありません)。

他の人は、機能の違いに関する主な質問についてすでに投稿しています。しかし...

javascriptでこれらのメソッドを実際に使用する方法はありますか(データベースを更新していないため)。

...おかしいです。ちょうど今日、変換のためにmapを使用して、正規表現の値を複数の変数に割り当てるコードを作成しました。非常に複雑なテキストベースの構造を視覚化可能なデータに変換するために使用されました...しかし、簡単にするために、日付文字列を使用した例を提供します。 、mapの代わりにDate-objectを使用します。Date-objectは、それ自体で見事にジョブを実行します)。

const DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z$/;
const TEST_STRING = '2016-01-04T03:20:00.000Z';

var [
    iYear,
    iMonth,
    iDay,
    iHour,
    iMinute,
    iSecond,
    iMillisecond
    ] = DATE_REGEXP
        // We take our regular expression and...
        .exec(TEST_STRING)
        // ...execute it against our string (resulting in an array of matches)...
        .slice(1)
        // ...drop the 0th element from those (which is the "full string match")...
        .map(value => parseInt(value, 10));
        // ...and map the rest of the values to integers...

// ...which we now have as individual variables at our perusal
console.debug('RESULT =>', iYear, iMonth, iDay, iHour, iMinute, iSecond, iMillisecond);

したがって...これは単なる例であり、データの非常に基本的な変換のみを行いました(例のためだけ)...マップなしでこれを行うと、はるかに退屈な作業になります。

確かに、JavaScriptのバージョンで書かれているので、あまり多くのブラウザーがサポートしているとは思わないまだ(少なくとも完全に)だが、私たちはそこに着いている。ブラウザで実行する必要がある場合、うまく変換できると思います。

0
Markku Uttula

TL; DR回答-

mapは常に別の配列を返します。

forEachはしません。何をするかはあなた次第です。必要な場合は配列を返し、不要な場合は他の操作を行います。

特定の状況では柔軟性が望ましい。あなたが扱っているもののためではない場合は、マップを使用してください。

0
charsi