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 Joe Karlsson

Call, Apply, Bind....oh My

Summary of the application of call, apply and bind in JavaScript. Their similarities and differences and application.

  • 1,877