How to use call(), apply(), bind() in JavaScript?

In JavaScript objects have their own properties and methods. With every function we have three methods: call(), apply() and bind().

Before moving into this concept, first lets have a recap on this in functions. This keyword determines how a function is called (runtime binding).

There is a feature in JavaScript which allows to use the methods of some other objects to another object without redefining them. This way of borrowing is done through call(), apply(), bind() methods.

Call(), apply(), and bind() methods are used to set the this keyword independent of function call. Useful in callbacks.

Call():

Call method sets the this inside function and immediately executes the function. Here you can pass arguments as a list.

Syntax:

function.call(thisArg, arg1, arg2, …)

function – function that needs to be invoked with different this object.

thisArg – value that needs to be replaced with this keyword present inside this function.

arg1,arg2,… – arguments passed for invoking function with this.

Example:
 function test(arg1, arg2){
   console.log(this.num, arg1, arg2); // 100, 10, 20
}

test.call({num: 100}, 10, 20);
Output:

100,10,20

apply()

apply() method binds the this value to the function and executes the function. Here  you can pass argument as an array.

Syntax:
function.apply(this, [argumentsArray])

It returns the result of the function which is invoked by this.

function test(...args){
  console.log(this.num, args);//100, [1,2,3]
}
test.apply({num: 100}, [1,2,3]);
Output:

100, [1,2,3]

Bind()

Bind() function binds this value to the function and returns new function. We need to invoke the returned function separately.

Syntax:
function.bind(this,arg1,arg2,arg3,...)

Bind returns a copy of function with this and arguments.

function test(arg){

 console.log(this.number, arg);

}

let bindedFn = test.bind({number: 1}, "Abaython");

bindedFn();
Output:

1 Abaython

Differences : call() vs apply() vs bind()

call()apply()bind()
DefinitionCall method is a predefined javascript method. With call an object can use a method belonging to another object. Here we supply list of argumentsSimilar to call(). But here we supply array of argumentsBind() helps in creating another function and execute later with new this function
ExecutionAt time of bindingAt time of bindingAt time when we execute the return function
Return?Yes it returns and calls the same function at time of bindingYes it returns and calls the same function at time of bindingYes it returns a new function of copy of function which can be used later.
ParameterList of argumentsArray of argumentsArray and any number of arguments

Key points to note:

  • call: binds the this value, invokes the function, and allows you to pass a list of arguments.
  • apply: binds the this value, invokes the function, and allows you to pass arguments as an array.
  • bind: binds the this value, returns a new function, and allows you to pass in a list of arguments.

How to destructure arrays and objects in JavaScript?

Before getting into destructuring, lets have a quick recap on arrays and objects.

  • Objects allows us to create a single entity that gather data items by key.

const emp = {

  name: “Anna”,

  id: “101”,

};

  • Array allows us to gather data items into an ordered list.

const emp = [“Anna”,”Tina”,”Tim”];

Destructuring introduced in ES6 allows us to unpack elements in an array or elements. It extracts multiple properties, items and values from an array or object into a separate variable.

Object Destructuring:

Syntax:
let { var1,var2} ={var1:val1, var2:val2}

To destruct object we use curly braces { }

Consider you have a student object with properties firstname and lastname.

let student = {

    firstname: "Anna",

    lastname: "Hills"

};
Prior to ES6:

For assigning properties and values to variables we have,

let student = {

    firstname: “Anna”,

    lastname: “Hills”

};

let firstName = student.firstname;

let lastName = student.lastname;

console.log(firstName);

console.log(lastName);

From ES6:
// assigning object attributes to variables
let student = {
    firstname: "Anna",
    lastname: "Hills"
};
// destructuring assignment
let { firstname, lastname} = student;
console.log(firstname); // Anna
console.log(lastname); // Hills
In the above example we have used the same variable names.
How to assign new variable name?
// assigning object attributes to variables
let student = {
    firstname: "Anna",
    lastname: "Hills"
};
// destructuring assignment to new variable
let { firstname:fname, lastname:lname} = student;
console.log(fname); // Anna
console.log(lname); // Hills

The order of the name in the object is not important we can also write as,

let {lastname, firstname} = student;
How to assign default values?

We can pass default values as follows,

let student = {
    firstname: "Anna",
    lastname: "Hills"
};
let { firstname, lastname, age = 22} = student;
console.log(age); //22
Output:

22

How to assign multiple object properties to single variable?
const student = {
    firstname: 'Anna',
    lastname: 'Hills',
    age: 25,
    gender: 'female'    
}
// destructuring assignment
// assigning remaining properties to rest
let { firstname, ...details } = student;

console.log(firstname); // Anna
console.log(details); // {lastname: 'Hills', age: 25, gender: 'female'}
Output:

Anna

{ lastname: ‘Hills’, age: 25, gender: ‘female’ }

Nested destructuring in objects:

In order to execute the nested destructuring assignment for objects, you have to enclose the variables in an object structure (by enclosing inside {}).

const student = {
    name: 'Anna',
    age: 26,
    details: {
        course: 'Javascript',
        fee: 2500
    }
}
// nested destructuring 
const {name, details: {course, fee}} = student;
console.log(name); // Anna
console.log(course); // Javascript
console.log(fee); // 2500
Output:

Anna

Javascript

2500

Array destructuring:

To destruct arrays we use square brackets [ ].

Syntax:
const [var1,var2,…] = arrayName;
Example:
const arrValue = ['Anna', 'Tina', 'Lena'];

// destructuring assignment in arrays
const [x, y, z] = arrValue;

console.log(x); 
console.log(y); 
console.log(z); 
Output:

Anna

Tina

Lena

How to assign default values?
let arr1 = [20];
// assigning default value 5 and 7
let [x = 10,  y = 9] = arr1;
console.log(x); // 20
console.log(y); // 9

In the above array we have one element so when we assign default values only y=9 is assigned and x=20 remains the same.

Output:

20

9

How to swap variables using destructuring assignment?
// program to swap variables
let x = 10;
let y = 20;
// swapping variables
[x, y] = [y, x];
console.log(x); // 20
console.log(y); // 10
Output:

20

10

How to skip assigning unwanted items in an array?

We can skip assigning unwanted items in an array to a local variable using comma ( , )

const arr1 = ['one', 'two', 'three'];
// destructuring assignment in arrays
const [x, , z] = arr1;
console.log(x); // one
console.log(z); // three
Output:

one

three

How to assign multiple elements to a single variable?

We can assign multiple elements to a single variable using spread syntax …

const arr1 = ['one', 'two', 'three', 'four'];
// destructuring assignment in arrays
// assigning remaining elements to y
const [x, ...y] = arr1;
console.log(x); // one
console.log(y); // ["two", "three", "four"]
Output:

one

[ ‘two’, ‘three’, ‘four’ ]

one is assigned to x variable. Rest of the elements are assigned to y variable.

Nested Destructuring Assignment in arrays:

In order to execute the nested destructuring assignment, you have to enclose the variables in an array structure (by enclosing inside []).

Nested destructuring in arrays is

// nested array elements
const arr1 = ['one', ['two', 'three', 'four']];
// nested destructuring assignment in arrays
const [a, [b, c, d]] = arr1;
console.log(a); // one
console.log(b); // two
console.log(c); // three
console.log(d); // four
Output:

one

two

three

four

Destructuring allows for instantly mapping an object or array to many variables.

How to implement Queue in Javascript?

The main principle of queue datastructure is FIFO (First in First Out). If we compare with real life queue example, people standing in a queue are nodes. Queue implementation can be done in two ways: using array and using object.

Implement Queue using array:

First we create an array named queue.

Second we push some elements using push()

Third we remove elements using shift()

Fourth to check if the queue is empty we use queue.length and see whether empty or not

// Initializing queue array.
var queue = [];

// Inserting vales into the queue.
queue.push(1);
queue.push(2);
queue.push(3);
queue.push(4);
queue.push(5);

console.log("The current queue is: ", queue);

// Removing element form queue using array method: shift()
var removed_element = queue.shift();
console.log("Removed element is: ", removed_element);

console.log("The current queue is: ", queue);

// We can check the if the queue is empty or not using the array.length method.
if (queue.length > 0) {
  console.log("The Queue is not empty!");
} else {
  console.log("The Queue is empty!");
}
Output:

Using objects:

Here we will create a class node.

class Node {
    constructor(value) {
        this.value = value;
        this.next = null;
    }
}
This class has 2 parameters:
  • this.value – the value which node stores
  • this.next – the pointer to next node in queue and initially it is assigned to null as there is no nodes in queue

Now we need to create another class to store all the nodes and perform queue operations.

class Queue {
    constructor() {
        this.head = null;
        this.tail = null;
        this.length = 0;
    }
}
This class has 3 properties:
  • this.head – pointer to first node
  • this.tail -pointer to last node
  • this.length – number of nodes in queue
Methods of a queue:
  • enqueue() – To add elements at rear end of the queue
  • dequeue() – To remove elements from front end of the queue
  • peek() – To get the front element without removing it.
  • isEmpty() – To check whether an element is present in the queue or not.
  • print()  – To print the elements in the queue
  • getLength() – Returns the number of nodes in a queue.
class Node {
    constructor(value) {
        this.value = value;
        this.next = null;
    }
}

class Queue {
    constructor() {
        this.head = null;
        this.tail = null;
        this.length = 0;
    }

    enqueue(value) {
        const node = new Node(value);

        if (this.head) {
            this.tail.next = node;
            this.tail = node;
        } else {
            this.head = node;
            this.tail = node
        }

        this.length++;
    }

    dequeue() {
        const current = this.head;
        this.head = this.head.next;
        this.length--;

        return current.value;
    }

    isEmpty() {
        return this.length === 0;
    }

    peek() {
        return this.head.value;
    }

    getLength() {
        return this.length;
    }

    print() {
        let current = this.head;

        while(current) {
            console.log(current.value);
            current = current.next;
        }
    }
}

const queue = new Queue();
console.log('is empty?', queue.isEmpty())
queue.enqueue(12)
queue.enqueue(24)
queue.enqueue(36)
queue.enqueue(48)
queue.enqueue(60)
console.log('Queue:')
queue.print()
console.log('Remove 2 elements')
queue.dequeue()
queue.dequeue()
console.log('Queue:');  queue.print()
console.log('is empty?', queue.isEmpty())
console.log('Length',    queue.getLength())
console.log('Head', queue.peek())
Output:

To know more about the data structures in javascript click here!

Higher Order Functions and decorators in Python

Higher Order Functions:

Higher Order Functions (HOFs) are functions that express complex concepts by combining simpler functions into a new function. It is a function that contains a function as parameter and returns another function as a result.

Properties of Higher Order Functions:

  1. We can store a function inside a variable.
  2. A function can act as instance of an object
  3. We can pass a function as an argument to another function
  4. We can store Python higher order functions in data structures such as list, hash tables etc.,

Functions as object:

               In Python, a function can be assigned to a variable. Here, a reference to the function is created.

Example:

Passing Function as an argument to another function:

Functions are like objects in Python, so they can be passed as an argument to another function.

Returning Function:

As functions are objects, we can also return a function from another function.

Decorators as Higher Order Function:

               We can use decorators as higher order function. Decorators in Python allow us to extend behavior of methods or functions without explicitly modifying it.

Decorators allow us to wrap another function to extend the behavior of wrapped function, without modifying it.

Syntax:

# Using a decorator  

@myDecorator  

def Python_Decorator():   

.

.

The above decorator syntax is equivalent to the below syntax for using decorator as higher order function in python.

def Python_Decorator():   

    .  

    .  

Python_Decorator = @myDecorator(Python_Decorator)  

Example:

In the next article we will see about map(), reduce() and filter() higher order functions.