私はすでにapply
とcall
がsetthis
(関数のコンテキスト)に似た関数であることを知っています。
違いは、引数の送信方法(manual vs array)です。
質問:
しかし、いつbind()
メソッドを使うべきですか?
var obj = {
x: 81,
getX: function() {
return this.x;
}
};
alert(obj.getX.bind(obj)());
alert(obj.getX.call(obj));
alert(obj.getX.apply(obj));
その関数が後で特定のコンテキストで呼び出されるようにしたい場合は.bind()
を使用してください。これはイベントに便利です。関数をすぐに呼び出してコンテキストを変更する場合は、.call()
または.apply()
を使用してください。
Call/applyは直ちに関数を呼び出しますが、bind
は後で実行されたときに元の関数を呼び出すための正しいコンテキストセットを持つ関数を返します。こうすることで、非同期コールバックとイベントでコンテキストを維持できます。
私はこれをたくさんします:
function MyObject(element) {
this.Elm = element;
element.addEventListener('click', this.onClick.bind(this), false);
};
MyObject.prototype.onClick = function(e) {
var t=this; //do something with [t]...
//without bind the context of this function wouldn't be a MyObject
//instance as you would normally expect.
};
私はメンバーメソッドを渡したい非同期コールバックのためにNode.jsで広く使用していますが、それでもコンテキストを非同期アクションを開始したインスタンスにしたいのです。
Bindの単純で素朴な実装は次のようになります。
Function.prototype.bind = function(ctx) {
var fn = this;
return function() {
fn.apply(ctx, arguments);
};
};
それ以外にも(他の引数を渡すのと同じように)ありますが、それについてもっと読んで、実際の実装 MDN上 を見ることができます。
お役に立てれば。
それらはすべて this を関数(またはオブジェクト)に付加します。違いは関数呼び出しにあります(下記参照)。
call は this を関数に付加し、その関数を直ちに実行します。
var person = {
name: "James Smith",
hello: function(thing) {
console.log(this.name + " says hello " + thing);
}
}
person.hello("world"); // output: "James Smith says hello world"
person.hello.call({ name: "Jim Smith" }, "world"); // output: "Jim Smith says hello world"
bind attach this を機能に追加するため、次のように個別に呼び出す必要があります。
var person = {
name: "James Smith",
hello: function(thing) {
console.log(this.name + " says hello " + thing);
}
}
person.hello("world"); // output: "James Smith says hello world"
var helloFunc = person.hello.bind({ name: "Jim Smith" });
helloFunc("world"); // output: Jim Smith says hello world"
またはこのように:
...
var helloFunc = person.hello.bind({ name: "Jim Smith" }, "world");
helloFunc(); // output: Jim Smith says hello world"
apply は call と似ていますが、引数を1つずつ一覧表示するのではなく、配列のようなオブジェクトを使用する点が異なります。
function personContainer() {
var person = {
name: "James Smith",
hello: function() {
console.log(this.name + " says hello " + arguments[1]);
}
}
person.hello.apply(person, arguments);
}
personContainer("world", "mars"); // output: "James Smith says hello mars", note: arguments[0] = "world" , arguments[1] = "mars"
SIMPLEST形式で回答する
電話
var person1 = {firstName: 'Jon', lastName: 'Kuperman'};
var person2 = {firstName: 'Kelly', lastName: 'King'};
function say(greeting) {
console.log(greeting + ' ' + this.firstName + ' ' + this.lastName);
}
say.call(person1, 'Hello'); // Hello Jon Kuperman
say.call(person2, 'Hello'); // Hello Kelly King
適用
var person1 = {firstName: 'Jon', lastName: 'Kuperman'};
var person2 = {firstName: 'Kelly', lastName: 'King'};
function say(greeting) {
console.log(greeting + ' ' + this.firstName + ' ' + this.lastName);
}
say.apply(person1, ['Hello']); // Hello Jon Kuperman
say.apply(person2, ['Hello']); // Hello Kelly King
バインド
var person1 = {firstName: 'Jon', lastName: 'Kuperman'};
var person2 = {firstName: 'Kelly', lastName: 'King'};
function say() {
console.log('Hello ' + this.firstName + ' ' + this.lastName);
}
var sayHelloJon = say.bind(person1);
var sayHelloKelly = say.bind(person2);
sayHelloJon(); // Hello Jon Kuperman
sayHelloKelly(); // Hello Kelly King
電話と申し込みはかなり互換性があります。配列とカンマ区切りの引数リストのどちらを送信するのが簡単かを決めてください。
Callはコンマ(区切りリスト)用で、ApplyはArray用です。
バインドは少し異なります。新しい関数を返します。 Call and Applyは直ちに現在の機能を実行します。
バインドは多くのことに最適です。上の例のように関数をカレーするためにそれを使うことができます。単純なhello関数を取り、それをhelloJonまたはhelloKellyに変えることができます。また、onClickのようなイベントが発生した場合には発生しませんが、コンテキストをどのようなコンテキストにしたいのかがわかっている場合にも使用できます。
参照: codeplanet.io
関数がどのように呼び出されるかとは無関係にthis
の値を設定することができます。これは、コールバックを扱うときにとても役に立ちます。
function sayHello(){
alert(this.message);
}
var obj = {
message : "hello"
};
setTimeout(sayHello.bind(obj), 1000);
call
で同じ結果を得るには、このようになります。
function sayHello(){
alert(this.message);
}
var obj = {
message : "hello"
};
setTimeout(function(){sayHello.call(obj)}, 1000);
multiplication
関数があるとします
function multiplication(a,b){
console.log(a*b);
}
bind
を使っていくつかの標準関数を作成しましょう。
var multiby2 = multiplication.bind(this,2);
これでmultiby2(b)は乗算(2、b)と等しくなります。
multiby2(3); //6
multiby2(4); //8
両方のパラメータをbindで渡すとどうなりますか
var getSixAlways = multiplication.bind(this,3,2);
これでgetSixAlways()は乗算(3,2)と等しくなります。
getSixAlways();//6
パラメータを渡しても6を返します。 getSixAlways(12); //6
var magicMultiplication = multiplication.bind(this);
これは新しい乗算関数を作成し、それをmagicMultiplicationに割り当てます。
いいえ、乗算機能をmagicMultiplicationに隠しています。
magicMultiplication
を呼び出すと、空白のfunction b()
が返されます。
実行時には正常に動作しますmagicMultiplication(6,5); //30
電話と申し込みはどうですか?
magicMultiplication.call(this,3,2); //6
magicMultiplication.apply(this,[5,2]); //10
簡単に言うと、bind
は関数を作成し、call
とapply
は関数を実行しますが、apply
は配列のパラメータを期待します
Function.prototype.call()
と Function.prototype.apply()
の両方の場合、指定されたthis
値を使用して関数を呼び出し、その関数の戻り値を返します。
一方、 Function.prototype.bind()
は、指定されたthis
の値で新しい関数を作成し、実行せずにその関数を返します。
それでは、このような関数を見てみましょう。
var logProp = function(prop) {
console.log(this[prop]);
};
それでは、このようなオブジェクトを見てみましょう。
var Obj = {
x : 5,
y : 10
};
このように関数をオブジェクトにバインドすることができます。
Obj.log = logProp.bind(Obj);
これで、コード内の任意の場所にObj.log
を実行できます。
Obj.log('x'); // Output : 5
Obj.log('y'); // Output : 10
それが本当におもしろくなるのは、this
の値をバインドするだけでなく、その引数prop
の値もバインドする場合です。
Obj.logX = logProp.bind(Obj, 'x');
Obj.logY = logProp.bind(Obj, 'y');
これができます。
Obj.logX(); // Output : 5
Obj.logY(); // Output : 10
bind :提供された値とコンテキストで関数をバインドしますが、関数を実行しません。機能を実行するには、機能を呼び出す必要があります。
call :与えられたコンテキストとパラメータで関数を実行します。
apply :与えられたコンテキストと パラメータを配列 として関数を実行します。
bind()
、apply()
、call()
の違いを説明するための 良い記事 を以下に要約します。
bind()
を使用すると、関数またはメソッドが呼び出されたときにどの特定のオブジェクトをthisにバインドするかを簡単に設定できます。
// This data variable is a global variable
var data = [
{name:"Samantha", age:12},
{name:"Alexis", age:14}
]
var user = {
// local data variable
data :[
{name:"T. Woods", age:37},
{name:"P. Mickelson", age:43}
],
showData:function (event) {
var randomNum = ((Math.random () * 2 | 0) + 1) - 1; // random number between 0 and 1
console.log (this.data[randomNum].name + " " + this.data[randomNum].age);
}
}
// Assign the showData method of the user object to a variable
var showDataVar = user.showData;
showDataVar (); // Samantha 12 (from the global data array, not from the local data array)
/*
This happens because showDataVar () is executed as a global function and use of this inside
showDataVar () is bound to the global scope, which is the window object in browsers.
*/
// Bind the showData method to the user object
var showDataVar = user.showData.bind (user);
// Now the we get the value from the user object because the this keyword is bound to the user object
showDataVar (); // P. Mickelson 43
bind()
はメソッドの借用を許可します
// Here we have a cars object that does not have a method to print its data to the console
var cars = {
data:[
{name:"Honda Accord", age:14},
{name:"Tesla Model S", age:2}
]
}
// We can borrow the showData () method from the user object we defined in the last example.
// Here we bind the user.showData method to the cars object we just created.
cars.showData = user.showData.bind (cars);
cars.showData (); // Honda Accord 14
この例の問題の1つは、showData
オブジェクトに新しいメソッドcars
を追加することです。また、carsオブジェクトには既にプロパティまたはメソッド名showData
が含まれている可能性があるため、メソッドを借用するだけではそうしたくない場合があります。誤って上書きしたくありません。以下のApply
およびCall
の説明で見るように、Apply
またはCall
メソッドを使用してメソッドを借用するのが最善です。
bind()
は、関数をカリー化することを許可します
Function Currying は、partial function applicationとも呼ばれ、一部の引数が既に設定されている新しい関数を返す関数(1つ以上の引数を受け入れる)。
function greet (gender, age, name) {
// if a male, use Mr., else use Ms.
var salutation = gender === "male" ? "Mr. " : "Ms. ";
if (age > 25) {
return "Hello, " + salutation + name + ".";
}else {
return "Hey, " + name + ".";
}
}
bind()
を使用して、このgreet
関数をカリー化できます
// So we are passing null because we are not using the "this" keyword in our greet function.
var greetAnAdultMale = greet.bind (null, "male", 45);
greetAnAdultMale ("John Hartlove"); // "Hello, Mr. John Hartlove."
var greetAYoungster = greet.bind (null, "", 16);
greetAYoungster ("Alex"); // "Hey, Alex."
greetAYoungster ("Emma Waterloo"); // "Hey, Emma Waterloo."
apply()
またはcall()
はthis値を設定します
apply
、call
、およびbind
メソッドはすべて、メソッドを呼び出すときにthis値を設定するために使用され、JavaScriptコードで直接制御と汎用性を使用できるようにわずかに異なる方法で設定します。
apply
メソッドとcall
メソッドは、この値を設定する場合、関数パラメーターをapply ()
にan arrayとして渡し、パラメーターを個別にリストする必要があることを除いて、ほとんど同じですcall ()
メソッドに渡します。
以下に、call
またはapply
を使用して、コールバック関数でthisを設定する1つの例を示します。
// Define an object with some properties and a method
// We will later pass the method as a callback function to another function
var clientData = {
id: 094545,
fullName: "Not Set",
// setUserName is a method on the clientData object
setUserName: function (firstName, lastName) {
// this refers to the fullName property in this object
this.fullName = firstName + " " + lastName;
}
};
function getUserInput (firstName, lastName, callback, callbackObj) {
// The use of the Apply method below will set the "this" value to callbackObj
callback.apply (callbackObj, [firstName, lastName]);
}
// The clientData object will be used by the Apply method to set the "this" value
getUserInput ("Barack", "Obama", clientData.setUserName, clientData);
// the fullName property on the clientData was correctly set
console.log (clientData.fullName); // Barack Obama
apply
またはcall
で関数を借用する
配列メソッドを借りる
array-like
オブジェクトを作成し、いくつかの配列メソッドを借用して、配列のようなオブジェクトを操作します。
// An array-like object: note the non-negative integers used as keys
var anArrayLikeObj = {0:"Martin", 1:78, 2:67, 3:["Letta", "Marieta", "Pauline"], length:4 };
// Make a quick copy and save the results in a real array:
// First parameter sets the "this" value
var newArray = Array.prototype.slice.call (anArrayLikeObj, 0);
console.log (newArray); // ["Martin", 78, 67, Array[3]]
// Search for "Martin" in the array-like object
console.log (Array.prototype.indexOf.call (anArrayLikeObj, "Martin") === -1 ? false : true); // true
別の一般的なケースは、次のようにarguments
を配列に変換することです
// We do not define the function with any parameters, yet we can get all the arguments passed to it
function doSomething () {
var args = Array.prototype.slice.call (arguments);
console.log (args);
}
doSomething ("Water", "Salt", "Glue"); // ["Water", "Salt", "Glue"]
他の方法を借りる
var gameController = {
scores :[20, 34, 55, 46, 77],
avgScore:null,
players :[
{name:"Tommy", playerID:987, age:23},
{name:"Pau", playerID:87, age:33}
]
}
var appController = {
scores :[900, 845, 809, 950],
avgScore:null,
avg :function () {
var sumOfScores = this.scores.reduce (function (prev, cur, index, array) {
return prev + cur;
});
this.avgScore = sumOfScores / this.scores.length;
}
}
// Note that we are using the apply () method, so the 2nd argument has to be an array
appController.avg.apply (gameController);
console.log (gameController.avgScore); // 46.4
// appController.avgScore is still null; it was not updated, only gameController.avgScore was updated
console.log (appController.avgScore); // null
apply()
を使用してvariable-arity関数を実行します
Math.max
は可変アリティ関数の一例です。
// We can pass any number of arguments to the Math.max () method
console.log (Math.max (23, 11, 34, 56)); // 56
しかし、Math.max
に渡す数字の配列がある場合はどうでしょうか?これはできません。
var allNumbers = [23, 11, 34, 56];
// We cannot pass an array of numbers to the the Math.max method like this
console.log (Math.max (allNumbers)); // NaN
ここでapply ()
メソッドがvariadic functionsの実行に役立ちます。上記の代わりに、apply (
)を使用して数値の配列を渡す必要があります:
var allNumbers = [23, 11, 34, 56];
// Using the apply () method, we can pass the array of numbers:
console.log (Math.max.apply (null, allNumbers)); // 56
直ちに/ apply / functionを実行します。
func.call(context, arguments);
func.apply(context, [argument1,argument2,..]);
bind は関数をすぐには実行しませんが、ラップされた apply functionを返します(後で実行するため)。
function bind(func, context) {
return function() {
return func.apply(context, arguments);
};
}
apply and bindを呼び出します。そしてそれらはどう違うのか。
電話を学び、毎日の用語を使用して適用することができます。
あなたは3つの自動車your_scooter , your_car and your_jet
を持っていて、それらは同じメカニズム(方法)で始まります。メソッドPush_button_engineStart
を使ってオブジェクトautomobile
を作成しました。
var your_scooter, your_car, your_jet;
var automobile = {
Push_button_engineStart: function (runtime){
console.log(this.name + "'s" + ' engine_started, buckle up for the ride for ' + runtime + " minutes");
}
}
電話や応募がいつ使用されるかを理解しましょう。あなたがエンジニアで、Push_button_engine_startに付属していないyour_scooter
、your_car
、およびyour_jet
があり、サードパーティのPush_button_engineStart
を使用したいとします。
次のコードを実行すると、エラーになります。どうして?
//your_scooter.Push_button_engineStart();
//your_car.Push_button_engineStart();
//your_jet.Push_button_engineStart();
automobile.Push_button_engineStart.apply(your_scooter,[20]);
automobile.Push_button_engineStart.call(your_jet,10);
automobile.Push_button_engineStart.call(your_car,40);
したがって、上記の例では、your_scooter、your_car、your_jetに自動車オブジェクトからのフィーチャが正しく与えられています。
もっと深く掘り下げましょう ここで、上記のコード行を分割します。 automobile.Push_button_engineStart
は、私たちが使用されているメソッドを取得するのを助けています。
さらに、applyを使うか、ドット表記を使って呼び出します。 automobile.Push_button_engineStart.apply()
今すぐ適用して呼び出す2つのパラメータを呼び出します。
そこで、ここではコードの最終行にコンテキストを設定します。
automobile.Push_button_engineStart.apply(your_scooter,[20])
callとapplyの違い は単にapplyが配列の形式でパラメータを受け取るのに対して、callは単にカンマ区切りの引数リストを受け取ることができるということです。
JS Bind関数とは何ですか?
バインド関数は基本的に何かのコンテキストをバインドし、それを後で実行するために変数に格納します。
前の例をさらに良くしましょう。以前は自動車のオブジェクトに属するメソッドを使い、それを使ってyour_car, your_jet and your_scooter
を装備しました。それでは、希望する実行の後期段階で自動車を個別に始動させるために、別々のPush_button_engineStart
を別々に与えることを想像してみましょう。
var scooty_engineStart = automobile.Push_button_engineStart.bind(your_scooter);
var car_engineStart = automobile.Push_button_engineStart.bind(your_car);
var jet_engineStart = automobile.Push_button_engineStart.bind(your_jet);
setTimeout(scooty_engineStart,5000,30);
setTimeout(car_engineStart,10000,40);
setTimeout(jet_engineStart,15000,5);
まだ満足していない?
それを涙としてはっきりさせましょう。実験する時間です。関数アプリケーションの呼び出しと適用に戻り、関数の値を参照として保存します。
Callとapplyはすぐに呼び出されるので、以下の実験は失敗します。したがって、バインド関数がショーを盗む場所である変数に参照を格納する段階には決して到達しません。
var test_function = automobile.Push_button_engineStart.apply(your_scooter);
呼び出し: 呼び出しは関数を呼び出し、引数を一つずつ渡すことを可能にします
適用: 適用は関数を呼び出し、配列として引数を渡すことを可能にします
Bind: Bindは新しい関数を返すので、この配列と任意の数の引数を渡すことができます。
var person1 = {firstName: 'Raju', lastName: 'king'};
var person2 = {firstName: 'chandu', lastName: 'shekar'};
function greet(greeting) {
console.log(greeting + ' ' + this.firstName + ' ' + this.lastName);
}
function greet2(greeting) {
console.log( 'Hello ' + this.firstName + ' ' + this.lastName);
}
greet.call(person1, 'Hello'); // Hello Raju king
greet.call(person2, 'Hello'); // Hello chandu shekar
greet.apply(person1, ['Hello']); // Hello Raju king
greet.apply(person2, ['Hello']); // Hello chandu shekar
var greetRaju = greet2.bind(person1);
var greetChandu = greet2.bind(person2);
greetRaju(); // Hello Raju king
greetChandu(); // Hello chandu shekar
Call、Apply、Bindの基本的な違いは次のとおりです。
画像の後半で実行コンテキストを取得する場合は、バインドが使用されます。
例:
var car = {
registrationNumber: "007",
brand: "Mercedes",
displayDetails: function(ownerName){
console.log(ownerName + ' this is your car ' + '' + this.registrationNumber + " " + this.brand);
}
}
car.displayDetails('Nishant'); // **Nishant this is your car 007 Mercedes**
他の変数でこのメソッドを使用したいとしましょう
var car1 = car.displayDetails('Nishant');
car1(); // undefined
他の変数で車の参照を使用するには、使用する必要があります
var car1 = car.displayDetails.bind(car, 'Nishant');
car1(); // Nishant this is your car 007 Mercedes
バインド関数のより広範な使用について話しましょう
var func = function() {
console.log(this)
}.bind(1);
func();
// Number: 1
どうして?現在funcはNumber 1でバインドされているため、その場合にバインドを使用しない場合、グローバルオブジェクトを指します。
var func = function() {
console.log(this)
}.bind({});
func();
// Object
Call、Applyは、ステートメントを同時に実行する場合に使用されます。
var Name = {
work: "SSE",
age: "25"
}
function displayDetails(ownerName) {
console.log(ownerName + ", this is your name: " + 'age' + this.age + " " + 'work' + this.work);
}
displayDetails.call(Name, 'Nishant')
// Nishant, this is your name: age25 workSSE
In apply we pass the array
displayDetails.call(Name, ['Nishant'])
// Nishant, this is your name: age25 workSSE
function printBye(message1, message2){
console.log(message1 + " " + this.name + " "+ message2);
}
var par01 = { name:"John" };
var msgArray = ["Bye", "Never come again..."];
printBye.call(par01, "Bye", "Never come again...");//Bye John Never come again...
printBye.call(par01, msgArray);//Bye,Never come again... John undefined
//so call() doesn't work with array and better with comma seperated parameters
//printBye.apply(par01, "Bye", "Never come again...");//Error
printBye.apply(par01, msgArray);//Bye John Never come again...
var func1 = printBye.bind(par01, "Bye", "Never come again...");
func1();//Bye John Never come again...
var func2 = printBye.bind(par01, msgArray);
func2();//Bye,Never come again... John undefined
//so bind() doesn't work with array and better with comma seperated parameters
想像してみてください、バインドは利用できません。次のように簡単に構成できます。
var someFunction=...
var objToBind=....
var bindHelper = function (someFunction, objToBind) {
return function() {
someFunction.apply( objToBind, arguments );
};
}
bindHelper(arguments);
function sayHello() {
//alert(this.message);
return this.message;
}
var obj = {
message: "Hello"
};
function x(country) {
var z = sayHello.bind(obj);
setTimeout(y = function(w) {
//'this' reference not lost
return z() + ' ' + country + ' ' + w;
}, 1000);
return y;
}
var t = x('India')('World');
document.getElementById("demo").innerHTML = t;