23

を使ったカリー化などのテクニックに頭を悩ませていFunction.prototype.bindます。特定の状況で
関数スコープ(つまり、値)を変更することは非常に便利なようです。this

ただし、一度変更するとスコープを変更できないようです。bind

function f = obj.method.bind(42); 
function g = obj.method.bind('Hi');

function f2 = f.bind('Hi'); // “this” is still 42

バインドされた関数から元のバインドされていない関数を取得することは可能ですか?

4

3 に答える 3

27

このbindメソッドが基本的に行うことは、次のようなものです(引数がスライスされてコンテキストが除外されるため、正確ではありません)。

function bind(context) {
    var self = this;
    return function() {
        self.apply(context, arguments);
    }
}

つまり、基本的には、指定されたコンテキストと引数を使用して自分自身を呼び出す別の関数を返します。その後bind、もう一度実行すると、この新しく作成された関数がバインドされます。これは、次のようbindに実装されたかのようになります。

 function bind(context) {
    var self = this;
    return function() {
        self.apply(context, arguments);
    }.bind(otherContext);
}

ただし、bindによって返される内部関数は、元のコンテキストが最初にバインドされたコンテキスト()であるクロージャーとして機能するためself、その1つが関数内のコンテキストになり、実際に実行されます。

于 2012-05-09T20:09:11.420 に答える
25

Win32の答えを写真で説明すると便利だと思いました。

によって生成されたラッパーは、関数が何であってもbind、指定されたコンテキストで呼び出されるようにします。 このようなラッパーは、常にそれ自体のコンテキストを無視します

ラッパーのチェーンが与えられると、最も内側以外のコンテキストは失われます。
したがって、を使用して設定したコンテキストを変更する方法はありませんbind

連鎖バインド呼び出し

于 2012-05-09T21:26:54.807 に答える
2

これは実際にあなたの問題を解決します

const bind = Function.prototype.bind;
Object.defineProperty(Function.prototype, 'bind', {
    value: function () {
        const result = bind.apply(this, arguments);
        result.source = (this.source || this);
        return result;
    }
});

これでsource、元の関数を取得するためのプロパティを取得できます。これは他の問題を引き起こす可能性がありますが、パフォーマンスはそれらの1つではないようです、https://jsperf.com/bind-override/1

IE、Edge、Firefox、Chromeの両方で同じ結果が得られるようです。通常のバージョンの方が速い場合もあれば、オーバーライドされた方が速い場合もあります。

于 2019-02-08T09:31:59.467 に答える