5

JavaScript で Array API の高次関数 (forEach、map、filter など) を使用する場合、「this」変数を渡す方法は 2 つあります。

myArray.forEach(function(value) {
    this.aContextualFunction();
}, this);

または

var self = this;
myArray.forEach(function(value) {
    self.aContextualFunction();
});

どちらが良いですか?長所と短所は何ですか?

例: http://jsfiddle.net/TkZgX/

4

2 に答える 2

3

私はいつも最初のものを好みます。

長所: 余分な var 宣言はありません

短所:この質問のコメントに見られるように、混乱するかもしれません..

于 2012-10-22T08:47:28.100 に答える
2

高階関数を使用する場合、私は自分の関数が引数として受け取るコールバックについて何も仮定しないことを好みます。一般に、コードが疎結合であるほど良い結果が得られます。

たとえば、次の高階関数を書いたとしますforEach

function forEach(array, callback, that) { // that is optional
    var length = array.length;
    for (var i = 0; i < length; i++)
        callback.call(that, array[i], i); // pass the value and the index
}

今、私はそれを使いたいと言います:

Array.prototype.double = function () {
    forEach(this, function (value, index) {
        this[index] = 2 * value;
    });                                     // oops, I forgot that
};

var array = [1, 2, 3];
array.double();

上記のコードにより、変数がグローバル スコープにリークします。良いことではありません。ここでデモを参照してください: http://jsfiddle.net/8dad4/

代替手段は何ですか?オプションの 3 番目のパラメーターを削除し、クロージャーを使用します。

function forEach(array, callback) {
    var length = array.length;
    for (var i = 0; i < length; i++)
        callback(array[i], i);
}

コードが小さくなるだけでなく、偶発的なグローバル リークが発生することもありません (バカみたいthisに外部の代わりに使用しない限り)。that例を見てみましょう:

Array.prototype.double = function () {
    var that = this;

    forEach(this, function (value, index) {
        that[index] = 2 * value;
    });
};

var array = [1, 2, 3];
array.double();

デモはこちら: http://jsfiddle.net/8dad4/1/

うーん...それはあまり魅力的ではないようです-新しい変数を作成したくありません。もっと良いことをしましょうか?はい、できます。これは私が好む方法です (まだ 2 番目のforEach関数を使用しています)。

Array.prototype.double = function () {
    forEach(this, function (value, index) {
        this[index] = 2 * value;
    }.bind(this));
};

var array = [1, 2, 3];
array.double();

デモはこちら: http://jsfiddle.net/8dad4/2/

うわー、これは良くないですか?方法 1 と 2 の両方を組み合わせました。利点:

  1. 関数はforEach何も仮定しません。コードはより疎結合です。
  2. のような外部変数は必要ありませんthat。閉鎖は必要ありません。
  3. 何が起こっているのか混乱はありません。

これができるのは、渡された無名関数がforEach関数式であるためです。したがって、それに追加.bind(this)するだけで完了です。

于 2012-10-22T10:29:29.450 に答える