In a programming language a function is a procedure or routine, better to say a piece of code which may take some inputs and process them to return a result.
Javascript started its journey from 1995 and day by day it improved and became the language of the web. From 2015 ECMAScript (a.k.a Javascript) promised to release new versions in every 1 or 2 years.
Like all other programming languages Javascript also provide us functions.
In Javascript, each function is an instance of Function class and each function has a different scope. It’s very important to understand the context and scope of every function. However, we can change the scope of a function in different ways to maintain the anonymity.
10 years before we could have used two representations of JS function but since 2015, Arrow Function representation has been introduced which help to shorten the JS codes.
In this blog we will discuss the various types of function representations in ES6 and some important methods of Function, which can help us to manipulate the scope.
Function declaration
In Javascript (upto ES5) there are two ways to declare a function. But there are some differences between this two declaration. If we declare a function in this way then we can call it before declaration.
The below code snippet is an example of first type of declaration
//Example var firstName = "Subhajit", lastName = "Ghosh"; getName(); function getName() { //Here this is the global context return (this.firstName + " " + this.lastName); };
Advantage of this function declaration is we can call the function before declaration.
In general, there are two steps to execute the JS code in a browser. First, the browser converts the code into a optimized code and then execute it by the interpreter.
So if we declare a function like var getName = function() {} before execution “getName” is just a variable. But in the previous function declaration the browser knows that “getName” is a function. So it’ll not return an error if execute the function before declaration.
//Example getName(); //Return an error 'undefined is not a function' var getName = function() { return (this.firstName + " " + this.lastName); };
Class/Constructor Function Declaration
This is a simple class better to say it is a constructor function representation of Javascript. It’s a good practice to always set default values for arguments of any type of function. If you didn’t pass any value to the function then it’ll not return any error and will execute everything using the default values.
var Person = function(firstName, lastName) { this.firstName = firstName || "Puja"; this.lastName = lastName || "Deora"; this.getName = function() { return (this.firstName + " " + this.lastName); } }
Use of Call and Apply
“call” and “apply” are two very important methods of Javascript Function. The behaviour of both the functions are almost same.”Call” takes the arguments of the functions one by one i.e. test.call (this, arg1, arg2…). On the other hand “apply” takes the arguments as an array i.e. test.apply (this, [arg1, arg2…]).
Using call and apply we can bind any scope to a function. In this example the scope of { firstName: “Santanu”, lastName: “Nandi” } this object binded with the getName function.
getName.call({ firstName: "Santanu", lastName: "Nandi" }); // Santanu Nandi //Another example of apply getName.apply({ firstName: "Sourav", lastName: "Mondal" }, []); //Sourav Mondal
Use of Bind
“bind” is one of my favourite method of Function in javascript, which helped me a lot to get rid of closures in some specific cases such as using parent scope in the callback function scope.
Let me explain it with a simple example. In this the Person object has a separate scope but on using bind method it will refer to its parent scope for this example it is the window scope.
var firstName = "Kittu", lastName = "Ghosh"; var Person = { firstName: "Puja", lastName: "Deora", getName: function() { return (this.firstName + " " + this.lastName); }.bind(this) // Here "this" refers to window scope, getNameWithoutBind: function() { return (this.firstName + " " + this.lastName); } }; Person.getName() //"Kittu Ghosh" Person.getNameWithoutBind() //"Puja Deora"
Here I, binded the window scope with the getName function. So it will always return the firstName and lastName which is declared in the window scope.
Person.getName.apply({ firstName: "ABC", lastName: "CDF" }); //"Kittu Ghosh" Person.getNameWithoutBind.apply({ firstName: "ABC", lastName: "CDF" }); //"ABC CDF"
If you bind the scope you cannot change the scope later. Look at the first example; there I tried to apply another object scope in getName function. After that also it returned me the firstName and lastName of window scope because it’s already binded with the window scope. But when I’m not using bind method as in getNameWithoutBind function it is working perfectly fine.
A brief introduction about ECMAScript 2015 (ES6)
On 1995 javascript was born as Livescript. After that 1997, ECMA standard established.On 1999 ES3 came. Finally on 2009 Douglas Crockford came up with the idea of OOP in javascript(ES5), what most of us use now. On 2015 ES6/ECMAScript2015 comes out with many syntactic sugar.
The new features of ES6 are:
In this blog we mainly focused on Arrow function representation and will discuss its advantage and disadvantage.
Arrow function representation in ES6
There is an another way to declare a function in ES6 which is known as Arrow function. Mainly this is a syntactic sugar on anonymous function declaration. Here is an example of arrow function.
let firstName = "Subhajit"; let lastName = "Ghosh"; let getName = () => (firstName + " " + lastName)
Advantages of arrow representation is it will reduce boring syntax of javascript functions. The flexibility of this type of representation is if the function has only one line return statement then we don’t need any {}.
Ex: let getName=() => (firstName +” “+lastName);
There are lot of disadvantage of arrow representation of function.If you declare a constructor function using arrow representation then it will bind the scope where it is declared.
// Never do this let Person = () => { this.firstName = "Subhajit"; this.lastName = "Ghosh"; this.getName = function() { return (this.firstName + " " + this.lastName); } } new Person().getName();
The above code snippet will return undefined undefined(For es2015-loose) as output because Person function binds the scope with window.
Note: for es2015-strict mode it will give you an error.
Good practice
class Person { constructor(firstName, lastName) { this.firstName = firstName || "Puja"; this.lastName = lastName || "Deora"; } getName() { return (this.firstName + " " + this.lastName); } } new Person().getName();
These are some more examples of playing with the scope of the functions.
Example 1
let obj = { firstName: "Subhajit", lastName: "Ghosh", obj2: { firstName: "Puja", lastName: "Deora", getName() { console.log(this.firstName + " " + this.lastName) } } } obj.obj2.getName() // Puja Deora
Example 2
let obj = { firstName: "Subhajit", lastName: "Ghosh", obj2: { firstName: "Puja", lastName: "Deora", getName: () => { console.log(this.firstName + " " + this.lastName) } } } obj.obj2.getName(); //undefined undefined (For es2015-loose)
In this example I have represented the getName() as an arrow function so the scope of getName() is representing the window scope, but this is a bad practice and it will throw an error in es2015-strict mode.
Example 3
var obj = { firstName: "Subhajit", lastName: "Ghosh", obj2: { firstName: "Puja", lastName: "Deora", getName: function() { console.log(this.firstName + " " + this.lastName) }.bind({ firstName: "Santanu", lastName: "Nandi" }) } } obj.obj2.getName() // Santanu Nandi
So, function scoping is a very important thing in Javascript and if you are not aware of this you can find difficulties while writing callback functions or overriding a library functions.
In this blog I just explained one feature of ES6 but many more to come. For more updates about ES6 follow Innofied blogs. And if you have any queries feel free to ask me out.