可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I already know that apply
and call
are similar functions which setthis
(context of a function).
The difference is with the way we send the arguments (manual vs array)
Question:
But when should I use the bind()
method ?
var obj = {
x: 81,
getX: function() {
return this.x;
}
};
alert(obj.getX.bind(obj)());
alert(obj.getX.call(obj));
alert(obj.getX.apply(obj));
jsbin
回答1:
Use .bind()
when you want that function to later be called with a certain context, useful in events. Use .call()
or .apply()
when you want to invoke the function immediately, and modify the context.
Call/apply call the function immediately, whereas bind
returns a function that, when later executed, will have the correct context set for calling the original function. This way you can maintain context in async callbacks and events.
I do this a lot:
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.
};
I use it extensively in Node.js for async callbacks that I want to pass a member method for, but still want the context to be the instance that started the async action.
A simple, naive implementation of bind would be like:
Function.prototype.bind = function(ctx) {
var fn = this;
return function() {
fn.apply(ctx, arguments);
};
};
There is more to it (like passing other args), but you can read more about it and see the real implementation on the MDN.
Hope this helps.
回答2:
They all attach this into function (or object) and the difference is in the function invocation (see below).
call attaches this into function and executes the function immediately:
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 attaches this into function and it needs to be invoked separately like 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\"
or like this:
...
var helloFunc = person.hello.bind({ name: \"Jim Smith\" }, \"world\");
helloFunc(); // output: Jim Smith says hello world\"
apply is similar to call except that it takes an array-like object instead of listing the arguments out one at a time:
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\"
回答3:
Answer in SIMPLEST form
- Call invokes the function and allows you to pass in arguments one by
one.
- Apply invokes the function and allows you to pass in arguments
as an array.
- Bind returns a new function, allowing you to pass in a
this array and any number of arguments.
Apply vs. Call vs. Bind Examples
Call
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
Apply
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
Bind
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
When To Use Each
Call and apply are pretty interchangeable. Just decide whether it’s easier to send in an array or a comma separated list of arguments.
I always remember which one is which by remembering that Call is for comma (separated list) and Apply is for Array.
Bind is a bit different. It returns a new function. Call and Apply execute the current function immediately.
Bind is great for a lot of things. We can use it to curry functions like in the above example. We can take a simple hello function and turn it into a helloJon or helloKelly. We can also use it for events like onClick where we don’t know when they’ll be fired but we know what context we want them to have.
Referance: codeplanet.io
回答4:
It allows to set the value for this
independent of how the function is called. This is very useful when working with callbacks:
function sayHello(){
alert(this.message);
}
var obj = {
message : \"hello\"
};
setTimeout(sayHello.bind(obj), 1000);
To achieve the same result with call
would look like this:
function sayHello(){
alert(this.message);
}
var obj = {
message : \"hello\"
};
setTimeout(function(){sayHello.call(obj)}, 1000);
回答5:
Assume we have multiplication
function
function multiplication(a,b){
console.log(a*b);
}
Lets create some standard functions using bind
var multiby2 = multiplication.bind(this,2);
Now multiby2(b) is equal to multiplication(2,b);
multiby2(3); //6
multiby2(4); //8
What if I pass both the parameters in bind
var getSixAlways = multiplication.bind(this,3,2);
Now getSixAlways() is equal to multiplication(3,2);
getSixAlways();//6
even passing parameter returns 6;
getSixAlways(12); //6
var magicMultiplication = multiplication.bind(this);
This create a new multiplication function and assigns it to magicMultiplication.
Oh no, we are hiding the multiplication functionality into magicMultiplication.
calling
magicMultiplication
returns a blank function b()
on execution it works fine
magicMultiplication(6,5); //30
How about call and apply?
magicMultiplication.call(this,3,2); //6
magicMultiplication.apply(this,[5,2]); //10
In simple words, bind
creates the function, call
and apply
executes the function whereas apply
expects the parameters in array
回答6:
Both Function.prototype.call()
and Function.prototype.apply()
call a function with a given this
value, and return the return value of that function.
Function.prototype.bind()
, on the other hand, creates a new function with a given this
value, and returns that function without executing it.
So, let\'s take a function that looks like this :
var logProp = function(prop) {
console.log(this[prop]);
};
Now, let\'s take an object that looks like this :
var Obj = {
x : 5,
y : 10
};
We can bind our function to our object like this :
Obj.log = logProp.bind(Obj);
Now, we can run Obj.log
anywhere in our code :
Obj.log(\'x\'); // Output : 5
Obj.log(\'y\'); // Output : 10
Where it really gets interesting, is when you not only bind a value for this
, but also for for its argument prop
:
Obj.logX = logProp.bind(Obj, \'x\');
Obj.logY = logProp.bind(Obj, \'y\');
We can now do this :
Obj.logX(); // Output : 5
Obj.logY(); // Output : 10
回答7:
bind: It binds the function with provided value and context but it does not executes the function. To execute function you need to call the function.
call: It executes the function with provided context and parameter.
apply: It executes the function with provided context and
parameter as array.
回答8:
Here is one good article to illustrate the difference among bind()
, apply()
and call()
, summarize it as below.
bind()
allows us to easily set which specific object will be bound to this when a function or method is invoked.
// 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()
allow us to borrow methods
// 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
One problem with this example is that we are adding a new method showData
on the cars
object and
we might not want to do that just to borrow a method because the cars object might already have a property or method name showData
.
We don’t want to overwrite it accidentally. As we will see in our discussion of Apply
and Call
below,
it is best to borrow a method using either the Apply
or Call
method.
bind()
allow us to curry a function
Function Currying, also known as partial function application, is the use of a
function (that accept one or more arguments) that returns a new function with some of the arguments already set.
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 + \".\";
}
}
We can use bind()
to curry this greet
function
// 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()
or call()
to set this value
The apply
, call
, and bind
methods are all used to set the this value when invoking a method, and they do it in slightly
different ways to allow use direct control and versatility in our JavaScript code.
The apply
and call
methods are almost identical when setting the this value except that you pass the function parameters to apply ()
as an array, while you have to list the parameters individually to pass them to the call ()
method.
Here is one example to use call
or apply
to set this in the callback function.
// 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
Borrow functions with apply
or call
Borrow Array methods
Let’s create an array-like
object and borrow some array methods to operate on the our array-like object.
// 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
Another common case is that convert arguments
to array as following
// 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\"]
Borrow other methods
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
Use apply()
to execute variable-arity function
The Math.max
is one example of variable-arity function,
// We can pass any number of arguments to the Math.max () method
console.log (Math.max (23, 11, 34, 56)); // 56
But what if we have an array of numbers to pass to Math.max
? We cannot do this:
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
This is where the apply ()
method helps us execute variadic functions. Instead of the above, we have to pass the array of numbers using apply (
) thus:
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
回答9:
call/apply executes function immediately:
func.call(context, arguments);
func.apply(context, [argument1,argument2,..]);
bind doesn\'t execute function immediately, but returns wrapped apply function (for later execution):
function bind(func, context) {
return function() {
return func.apply(context, arguments);
};
}
回答10:
- Call invokes the function and allows you to pass in arguments one by one.
- Apply invokes the function and allows you to pass in arguments as an array.
- Bind returns a new function, allowing you to pass in a this array and any number of arguments.
回答11:
Call apply and bind. and how they are different.
Lets learn call and apply using any daily terminology.
You have three automobiles your_scooter , your_car and your_jet
which start with the same mechanism (method).
We created an object automobile
with a method push_button_engineStart
.
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\");
}
}
Lets understand when is call and apply used. Lets suppose that you are an engineer and you have your_scooter
, your_car
and your_jet
which did not come with a push_button_engine_start and you wish to use a third party push_button_engineStart
.
If you run the following lines of code, they will give an error. WHY?
//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);
So the above example is successfully gives your_scooter, your_car, your_jet a feature from automobile object.
Let\'s dive deeper
Here we will split the above line of code.
automobile.push_button_engineStart
is helping us to get the method being used.
Further we use apply or call using the dot notation.
automobile.push_button_engineStart.apply()
Now apply and call accept two parameters.
- context
- arguments
So here we set the context in the final line of code.
automobile.push_button_engineStart.apply(your_scooter,[20])
Difference between call and apply is just that apply accepts parameters in the form of an array while call simply can accept a comma separated list of arguments.
what is JS Bind function?
A bind function is basically which binds the context of something and then stores it into a variable for execution at a later stage.
Let\'s make our previous example even better. Earlier we used a method belonging to the automobile object and used it to equip your_car, your_jet and your_scooter
. Now lets imagine we want to give a separate push_button_engineStart
separately to start our automobiles individually at any later stage of the execution we wish.
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);
still not satisfied?
Let\'s make it clear as teardrop. Time to experiment. We will go back to call and apply function application and try storing the value of the function as a reference.
The experiment below fails because call and apply are invoked immediately, hence, we never get to the stage of storing a reference in a variable which is where bind function steals the show
var test_function = automobile.push_button_engineStart.apply(your_scooter);
回答12:
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
回答13:
Imagine, bind is not available.
you can easily construct it as follow :
var someFunction=...
var objToBind=....
var bindHelper = function (someFunction, objToBind) {
return function() {
someFunction.apply( objToBind, arguments );
};
}
bindHelper(arguments);
回答14:
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;
回答15:
I think the same places of them are: all of them can change the this value of a function.The differences of them are: the bind function will return a new function as a result; the call and apply methods will execute the function immediately, but apply can accept a array as params,and it will parse the array separated.And also, the bind function can be Currying.
回答16:
bind function should be use when we want to assign a function with particular context for eg.
var demo = {
getValue : function(){
console.log(\'demo object get value function\')
}
setValue : function(){
setTimeout(this.getValue.bind(this),1000)
}
}
in above example if we call demo.setValue() function and pass this.getValue function directly then it doesn\'t call demo.setValue function directly because this in setTimeout refers to window object so we need to pass demo object context to this.getValue function using bind. it means we only passing function with the context of demo object not actully calling function.
Hope u understand .
for more information please refer
javascript bind function know in detail