web-dev-qa-db-ja.com

Javascriptで既にバインドされている関数の引数をさらにバインドします

私は、javascriptのbind()がどのように機能するかについての考えを整理しようとしています。

もしそうなら

var f = function (a) { ... }
var g = f.bind(obj);
g(1)

その後、fはobjthisとして、1aとして呼び出します。

私が考えたのは、gがfのラッパー関数だということです。

しかし、私がするとき

var f = function (a) { ... }
var g = f.bind(obj);
g.call(1)

その後、fはthisおよびa undefinedとして1で呼び出されます。

したがって、gは単なるラッパーではなく、callが通常の関数とバインドされた関数を何らかの形で区別しているようです。

もう1つは、関数を部分的にこれ以上適用できないことです。

var f = function (a) { ... }
var g = f.bind(obj);
var h = g.bind(1);
h();

次に、objおよびthis undefinedとしてaでfが呼び出されます。

この動作の原因は何ですか?

編集

この質問の構造は実際には間違っています。どのように見えるべきかについての受け入れられた答えを参照してください(一般的に、callbindが常に最初の引数としてコンテキスト引数を必要とすることに気づいていません)。

26
Martin Pecka

bindを使用してオブジェクトを関数にバインドすると、オーバーライドできません。 MDNドキュメンテーション でわかるように、仕様に明確に記述されています。

」bind()関数は、呼び出される関数(バインドされた関数のターゲット関数)と同じ関数本体(ECMAScript 5用語の内部呼び出しプロパティ)で新しい関数(バインドされた関数)を作成します)この値をbind()の最初の引数にバインドし、オーバーライドできません。 "

つまり、次の場合も同様です。

g.call(1);

仕様に従っているブラウザでは、1ではなくobjとしてthisを取得します。

もちろん、複数の引数をバインドできます:

var sum = function(a, b, c) { return a + b + c };
var sumAB = sum.bind(null, 1, 5);
var sumC = sumAB.bind(null, 2);

console.log(sumC());

ただし、上書きできないため、コンテキストオブジェクトは常に最初のbindで指定されたものになります。

混乱を避けるために、 call の最初の引数はコンテキストオブジェクト(this)であり、残りの引数があります。

その意味は:

var obj = { foo: function(bar) { console.log(bar) } };

obj.foo('hello');

// equivalent to:
var foo = obj.foo;

foo.call(obj, 'hello');

それが役に立てば幸い。

45
ZER0

引数を渡したことはありません。コンテキストを設定するだけです。 callの最初の引数はコンテキスト(this)として受け取られ、引数2以降は呼び出された関数の引数1以降として受け取られます。一方、bindは新しいコンテキストで新しい関数を作成します—引数は呼び出されたときに渡されます。

最初のコードブロックから1を関数fの引数aとして渡す方法は次のとおりです。

f( 1 );
g( 1 );
g.call( this, 1 );
g.apply( this, [ 1 ] );
3
Barney