Call, Apply, Bind....oh My
What the....
"The apply() method calls a function with a given this value and arguments provided as an array (or an array-like object)."
The call() method calls a function with a given this value and arguments provided individually.
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
The easiest way to think about all of these is that these 3 methods allow you to use a prototype function of another object with your current object.
We use these methods to force the context inside of another function.
or....
call(), bind(), apply()
ALL functions have these methods automatically (defined on their prototype).
and....
Object.getOwnPropertyNames(Function.prototype);
//=> ["length", "name", "arguments", "caller", "constructor", "bind", "toString", "call",
"apply"]
So what's the difference?
call() and apply() both invoke the function immediately
bind() calls a function at a later time based on an when an event happens
call() vs. apply()
The original JavaScript author said..
...10 days bruh.
Seriously though..
The difference is that there's no difference EXCEPT in the way you pass arguments to them, and how you reference those objects inside your function.
call()
apply()
function destroyArray(item, color){
console.log('Jack move on: ' + color + ' ' + item);
for(var i = 0; i < this.length; i++){
console.log(this[i] + " " + item);
this[i] = this[i] + " " + item;
}
console.log('Destroyed: [' + this.toString() + ']');
}
var myNumberArray = [1,4,6,7];
destroyArray.call(myNumberArray, 'Taco', 'Yellow');
var myStringArray = ["I", "am", "not", "a", "taco"];
destroyArray.call(myStringArray, 'Banana', 'Pink');
function destroyArray(args){
console.log('Jack move on: ' + args.color + ' ' + args.item);
for(var i = 0; i < this.length; i++){
console.log(this[i] + " " + args.item);
this[i] = this[i] + " " + args.item;
}
console.log('Destroyed: [' + this.toString() + ']');
}
var myNumberArray = [1,4,6,7];
destroyArray.apply(myNumberArray, [{'item': 'Taco', 'color': 'Yellow' }]);
var myStringArray = ["I", "am", "not", "a", "taco"];
destroyArray.apply(myStringArray, [{'item': 'Banana', 'color': 'Pink'}]);
Takes an argument list
Takes an array of arguments
Use the one whose arguments signature best suits your intended use.
apply(this, [args])
REMEMBER: apply() takes an Array of arguments
Pro-tip: (a)pply takes an (a)rray
apply can be invoked on any function/method defined on any other object's prototype.
// Call a JavaScript function
var numbers = [5, 6, 2, 3, 7];
//Without using apply
var max = Math.max.apply(5,6,2,3,7);
/* using Math.min, this is actually null as Math doesn't use context for operations */
var max = Math.max.apply(null, numbers); //this would have no prototype since null is set and context
function CreateUser() {
this.name = arguments[0];
this.age = arguments[1];
}
var user = {};
CreateUser.apply(user, ['Jason', 88]);
console.log(user.name); // 'Jason'
console.log(user.age); // 88
function SendEmail(){
MailManAPI.send(this.address, this.text);
}
var email = {
address = 'jason@devleague.com',
text = 'Aloooooha'
};
SendEmail.apply(email); //sends e-mail with unique values from existing object
call(this, arg1, arg2,...)
REMEMBER: call() takes a list of arguments
call can be invoked on any function/method defined on any other object's prototype.
// Call a JavaScript function
//Without using call
var max = Math.max(5,6,2,3,7);
/* using Math.min, this is actually null as Math doesn't use context for operations */
var max = Math.max.call(null, 5, 6, 2, 3, 7); //this would have no prototype since null is set and context
function CreateUser(name, age) {
this.name = name;
this.age = age;
}
var user = {};
CreateUser.call(user, 'Jason', 88);
console.log(user.name); // 'Jason'
console.log(user.age); // 88
function SendEmail(){
MailManAPI.send(this.address, this.text);
}
var email = {
address = 'jason@devleague.com',
text = 'Aloooooha'
};
SendEmail.call(email); //sends e-mail with unique values from existing object
bind()
Remember:
bind() binds a function to an element to be executed on a future event (click, hover,..)
bind() also takes a list of arguments like..?
call() !!
bind(this, arg1, arg2,...)
REMEMBER: bind() takes a list of arguments
bind can be bound to any function/method defined on any other object's prototype.
//Set property x on global scope
this.name = 'Jason';
var human = {
name: 'Jane',
getName: function() { return this.name; }
};
//here we call the function in the context of an object
human.getName(); // 'Jane'
//Get reference not to object and it's property but direct to the function
var getName = human.getName;
getName(); // 'Jason' "this" refers to the global object since it's not being
// invoked in the context of the object that defined it
// Create a new function with 'this' bound to module
var boundGetName = getName.bind(human); //Doesn't invoke now, it says WHEN that
// functions called, invoke it with the provided context
//NOW we invoke it
boundGetName(); // 'Jane'
// same as module.getName() but could also be invoked with another object to extract the
// function for use with other objects
var alien = {
name: 'Mork',
};
// Now invokes the original human function with a new object as it's context
var boundAlienGetName = getName.bind(alien);
boundAlienGetName(); // 'Mork'
var myObject = {};
//you can add properties(values) and methods(functions) to an object
myObject.name = 'Sam Object';
myObject.whatIsMyName = function() {
return this.name;
}
console.log(myObject.whatIsMyName()); // 'Sam Object'
var func = myObject.whatIsMyName;
var otherObject = {
name: 'Jason Jay'
};
var boundFunc = func.bind(otherObject);
console.log(boundFunc());
func.bind(otherObject);
console.log(func()); //This won't work
Must store reference to bound function. Cannot invoke directly. bind() returns a "bound" instance of the function.
Partial Functions
Partial functions are a way to define some arguments but have others be dynamic
function incrementMe(a, b){
return a + b;
}
//set incrementer value
var singleIncrementer = incrementMe.bind(null, 1);
singleIncrementer(4); // 5
//set incrementer value
var quintupleIncrementer = incrementMe.bind(null, 5);
quintupleIncrementer(4); // 9
// John Resig's "curry" function from
// http://ejohn.org/blog/partial-functions-in-javascript/
// which is unfortunately named, as this is not currying -
// it's partial function application.
Function.prototype.curry = function() {
//console.log(this, arguments);
var fn = this, args = Array.prototype.slice.call(arguments);
return function() {
//console.log(this, arguments);
return fn.apply(this, args.concat(
Array.prototype.slice.call(arguments)));
};
};
// a sample use
function add(a, b){
return a + b;
}
var partial = add.curry(1);
partial(2); //=> 3
https://lostechies.com/derickbailey/2012/07/20/partially-applied-functions-in-javascript/
Partial Method and Closures
Call, Apply, Bind....oh My
By Jason Sewell
Call, Apply, Bind....oh My
Summary of the application of call, apply and bind in JavaScript. Their similarities and differences and application.
- 2,324