3

次のサンプル Javascript コードがあるとします。

var modeller = "foo";
var provider1 = function (modeller, content, optionalArg) {
    alert("this: " + this + ", content: " + content + ", optionalArg: " + optionalArg);
}.bind(null, modeller);

var provider2 = function (content, optionalArg) {
    alert("this: " + this + ", content: " + content + ", optionalArg: " + optionalArg);
};

var createConsumer = function () {
    // some arbitrary private vars
    var content = 1; 
    var option = 2; 

    var doConsume = function(provider) {
        provider.apply(this, [content, option])
    };
    return {consume: doConsume};
};

// Now use them
var consumer = createConsumer();

consumer.consume(provider1);
consumer.consume(provider2);

これはデモ用に大幅に簡略化されていますが、要点はprovider1既にバインドされており、バインドされていないということです。消費者は自分自身を の引数provider2として渡すことはできません。thisprovider1

質問:関数が既にバインドされているこの種のケースを検出する方法はありますか? provider1コンシューマを次のように使用する方法はありthisますか? 答えが「いいえ」であると仮定すると、この種の状況を回避する最善の方法は何ですか?

4

3 に答える 3

4

「関数が既にバインドされているこの種のケースを検出する方法はありますか?」

いいえ。

「 asprovider1を使用する方法はありますか?」consumerthis

いいえ。

「……このような状況を回避する最善の方法は何ですか?」

値ではなく引数をバインドしたいように思われるので、 ではなく、引数のみがバインドされた関数を返すthis引数バインダー メソッドを作成します。Function.prototypethis

Function.prototype.argBind = function() {
    var _slicer = [].slice,
        orig_args = _slicer.call(arguments),
        orig_func = this;
    return function() {
        return orig_func.apply(this, orig_args.concat(_slicer.call(arguments)));
    };
};

次に、次のように使用します。

var modeller = "foo";
var provider1 = function (modeller, content, optionalArg) {
    alert("this: " + this + ", content: " + content + ", optionalArg: " + optionalArg);
}.argBind(modeller);

これで、関数は指定された通常の値provider1で呼び出されますが、最初の引数としてバインドされます。thismodeller

于 2012-11-06T20:04:19.630 に答える
0

apply() と call() の最初の引数が、バインドされた関数内の「this」の値を変更しないことを示すサンプル コードを次に示します。

let bf = f .bind  (123);
let n  = bf.call  (234);
let n2 = bf.apply (234);
ok (n  === 123);
ok (n2 === 123);

function f ()
{ return this;
}

( 上記の ok() は、真実ではない引数で呼び出された場合にエラーをスローする関数です)。

関数がバインドされているかどうかを検出できますか?

上記のMihai Voicescuの答えは、私の見解では正しいようです。そのバリエーションは次のようになります。

後で「バインド性」をテストする関数のソースコード内のコメントに、一意の文字列 (関数の作成者としての名前など) を配置します。テストされている関数の toString() を取ります。元のソースにある一意の文字列が含まれていない場合は、それが制限されていることがわかります。いつものように、サポートしたいブラウザーをテストするのが最善です。

この状況を回避する最善の方法は何ですか?

通常のオプションの引数を使用して、「substitute-this」として使用するオブジェクトを渡します。たとえば、それを「自分」と呼びます。「self」引数は、デフォルト値が「this」であることを宣言できます。次に、関数内で「this」の代わりに「self」を使用します。デフォルトでは、その値はバインドされた「this」と同じですが、オプションの引数「self」に明示的に別の値を渡すことで変更できます。バインドされた「this」を使用したい場合は、オプションの自己引数を渡す必要はまったくありません。

于 2021-04-17T17:31:32.937 に答える