4

JS で理解できない動作を経験しました。いくつかの引数を指定して String.prototype.replace を呼び出すメソッドを作成したかったため、次のように思いつきました。

String.prototype.replace.bind("foo", /bar/g, function(){}).call

私は、置換を取得するために文字列をスローするだけでよい関数を取得すると推測しました。代わりに、常に初期this値 (この場合fooは ) が返されます。

今私の質問は次のとおりです。

  • なぜJSはそのように振る舞うのですか?bind は実際に何を返し、どのようにしてthis-parameterを取得でき.call()ますか?
  • ラッパー関数を作成せずにやりたいことを行う別の方法はありますか?
4

3 に答える 3

2

Function.bind は、呼び出されると、バインドされたコンテキストで元の関数を常に呼び出す新しい関数を返します。

次のように Function.bind を実装できます。

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

ここでこれを試すことができます: http://jsfiddle.net/HeRU6/

したがって、 を実行するsomefunction.bind("foo")と、新しい関数が返されます。この新しい関数を呼び出すsomefunction"foo"、常にコンテキストとして呼び出されます。

コンテキストではなく、引数のみをバインドする関数を作成できます。

Function.prototype.curry = function() {
    var origFunction = this, args = Array.prototype.slice.call(arguments);
    return function() {
        console.log(args, arguments);
        return origFunction.apply(this, Array.prototype.concat.apply(args, arguments));
    };
};

a = function() { console.log(this, arguments); };

b = a.curry(1, 2);
b(); // Window [1, 2]
b(3); // Window [1, 2, 3]
b.call("foo", 4); // "foo" [1, 2, 4]
于 2011-08-27T10:10:02.933 に答える
2

なぜそれが起こっているのか

から返される関数に何らかのthis値を渡します。ただし、その値を無視し、バインドされた元の関数を呼び出します(例: )。実際、値をバインドするためのものです。バインドできるのは、むしろ追加の何かです。callbindbindthisfoobindthisarguments

それを解決する

ラッパー関数がないと、やりたいことができないと思います。ただし、ラッパー関数を使用すると、次のことができます。

Function.prototype.bindArgs = function() {
    var args = arguments,
        func = this;

    return function(context) {
        return func.apply(context, args);
    }
};

例えば

var func = function(a, b, c) {
    console.log(this, a, b, c);
};

var bound = func.bindArgs(1, 2, 3);
bound([1]); // [1] 1 2 3
bound({a: 1}); // {a: 1} 1 2 3
于 2011-08-27T10:14:04.090 に答える
1

なぜJSはそのように振る舞うのですか?

それが標準で定義されている方法だからです。

bind は実際に何を返しますか?また、.call() の this-parameter を取得するにはどうすればよいですか?

g = f.bind(foo, bar, ...)は とまったく同じなfunction g() { return f.call(foo, bar, ...); } ので、呼び出しから戻すことはできませんthisg

ラッパー関数を作成せずにやりたいことを行う別の方法はありますか?

おそらくそうではありません。

于 2011-08-27T10:16:39.963 に答える