0

次の点に注意してください。

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

array_map([1, 2, 3], function (x) { a.push(x); });
// just gives a = [1, 2, 3] as expected

// but why does this not work: ?
array_map([1, 2, 3], b.push);
// Chrome: a = [], Firefox: can't convert undefined to object

これが発生する理由を理解しています。つまり、直接渡すと、(グローバルオブジェクトでpushはなく)バインドされなくなります。Chromeでエラーが発生しない理由はよくわかりませんが、少なくともFirefoxでは何らかのエラーが発生するようです。barray_map

このようなバグarray_mapを回避するために、このような関数が渡されたかどうかをどのように検出できますか?

関数の原点を追跡するために利用できる高度な反射技術があることを望んでいます。たとえば、b.push.constructorを与えますがFunction、それは私が探しているものではありません。

4

3 に答える 3

2

あなたがそこで何が起こると期待しているのかわかりません。Array.prototype.map2番目のパラメーターとして関数が必要です。これは、反復ごとに新しい値を返します。

関数参照(2番目の例で行う)だけを渡すことは、とにかく関数に何をしなければならないかを伝えません。したがって、黒魔術を適用し、渡されたメソッドを正しいパラメーターで呼び出すことを期待してい.map()ますが、これは明らかにできません。

あなたがあなた自身のマッピング関数を書いたことを私は完全に知りませんでした。ただし、問題は、その関数のスコープを失っているということです。同様に.push()呼び出した場合にのみ、呼び出された関数内でターゲットオブジェクトが正しく参照されます。参照を渡した後は、グローバル/を指すか、または機能しなくなります。Array / Objectxxx.push()thisthiswindowundefined

だからあなたはそれを次のように呼ぶことができるその問題を解決します

array_map([1, 2, 3], b.push.bind(b));

ES5機能も適用されます。内で実際に検出することはできませんarray_map()。関数は関数です。渡されたメソッドがネイティブであるかどうかを検出するのが最善の方法ですが、これはお勧めしません。

于 2012-08-20T12:57:57.823 に答える
1

問題は、Javascriptには「メソッド」のようなものがないということです。これは特定のオブジェクトに排他的にバインドされた関数です。最初の例では、を呼び出す関数を渡しますa.push。 で直接呼び出すため、ここにthisバインドされます。a

2番目のコードでは、 -pushのコンテキストなしで関数を渡すだけで、gloablオブジェクトである実行コンテキストにバインドされます。bthis

次のように関数のコンテキストをバインドする必要があります。

array_map([1, 2, 3], b.push.bind(b));

またはjQueryのproxy()。現在、別の簡単な解決策を見つけることはできませんが、3番目のパラメーターでコンテキストを直接渡すための解決策を見つけることができます。function array_map(array, callback, context)

于 2012-08-20T13:09:23.817 に答える
1

通常、これらの種類の関数を使用すると、コールバックのコンテキストを設定できます。

コンテキストを受け入れるようにarray_map関数を変更すると、次のように機能します。

function array_map(array, callback, context) {
    for (var i = 0; i < array.length; i += 1) {
        callback.call(context, array[i]);
    }
}
var b = [];

// now the push method is called from the b context
array_map([1, 2, 3], b.push, b);
于 2012-08-20T13:17:32.843 に答える