JavaScript core concept: ES6, Function #JS Tutorial part3

Mahadiul Hasan
11 min readNov 3, 2020

JavaScript ES6/ES2015

New Features in ES6

  • The let keyword
  • The const keyword
  • JavaScript Arrow Functions
  • JavaScript Class
  • JavaScript Promise
  • JavaScript Symbol
  • Default Parameter Values
  • Function Rest Parameter
  • Array.find()
  • Array.findIndex()
  • New Number Properties
  • New Number Methods
  • New Global Methods

Var Declarations and Hoisting:

Variable declarations using var are treated as if they are at the top of the function (or global scope, if declared outside of a function) regardless of where the actual declaration occurs; this is called hoisting. Consider the examples below:

function getValue(condition){
if(condition){var value = 'blue'; return value}
else{ return null}
}

Behind the scenes, the JavaScript engine changes the getValue function to look like this:

function getValue(condition){
var value;
if(condition){value = 'blue'; return value}
else{ return null}
}

The declaration of value is hoisted to the top. The variable value is actually still accessible from within the else clause. If accessed from within the else clause, the variable value will be undefined because it hasn’t been initialized, it's initialized only in the If clause.

Block-Level Declarations:

1.Inside of a function
2.Inside of a block { \\code block }

Let Declarations
The let declaration syntax is the same as the syntax for var. You can basically replace var with let to declare a variable, but the limit is only the current code block. Here’s an example:

function getValue(condition){
if(condition){let value = 'blue'; return value}
else{ return null}
}

No Redeclaration:

If an identifier has already been defined in scope, then using the identifier in a let declaration inside that scope causes an error to be thrown. For example:

var count = 30;
let count = 40;

This next let declaration example doesn’t throw an error because it creates a new variable within the if statement. Inside the if block, this new variable shadows the global count but prevents access to it until execution leaves the block.

var count = 30;
if(condition){
let count = 40;
}

Constant Declarations:

You can also define variables with the const declaration syntax. Variables declared using const are considered constants, meaning their values cannot be changed once set. For this reason, every const variable must be initialized when declaration, as shown in this example:

const maxItems = 30;
const name;

Constants vs Let Declarations:

Constants are like let declarations which are block-level declarations. That means constants are no longer accessible once execution flows out of the block, const doesn’t hoist, as demonstrated in this example:

if(condition){
const maxItems = 5;
}

A const declaration throws an error when made with an identifier which is an already-defined variable in the same scope. It doesn’t matter variable was declared using var or let. For example, consider this code:

var message = 'Hello!';
let age = 25;
const message = 'Goodbye!';
const age =30;

Attempting to assign a const to a previously defined constant will throw an error, in both strict and non-strict modes:

const maxItems = 5;
maxItems = 6; //throw error

It wasn’t throwing an error in case of let. As an example below:

let maxItems = 5;
let = 6; //throw error

let maxItems = 5;

let = 6; // throws error

Declaring Objects with Const:

Const declarations for objects do not prevent modification of the objects. For example:

const person = {
name:'Rasel};
person.name = 'Greg';
// throws an error
person = {
name: 'Greg'
};

**Just remember: const prevents modification of the binding, not a modification of the bound value.

The Temporal Dead Zone:

A variable declared with either let or const cannot be accessed until after the declaration. Follow this example:

if (condition) {
console.log(typeof value); // ReferenceError!
let value = 'blue';
}

Block Binding in Loops:

This is one area where developers most want block-level scoping of variables is within for loops, where the throwaway counter variable is meant to be used only inside the loop. For for this we have to use let not var, cause var is being hoisted. Follow the two examples below:

for (var i = 0; i < 10; i++) {
process(items[i]);
}
// i is still accessible here
console.log(i); // 10

The variable i is still accessible after the loop is completed because the var declaration gets hoisted. Using let instead, as in the following code to ignore this problem:

for (let i = 0; i < 10; i++) {
process(items[i]);
}
// i is not accessible here — throws an error
console.log(i);

In this example, the variable i only exists within the for a loop.

Functions in Loops:

The characteristics of var have made creating functions inside of loops problematic because the loop variables are accessible from outside the scope of the loop. Consider the following code:

var funcs = [];for (var i = 0; i < 10; i++) {
funcs.push(function() { console.log(i); });
}
funcs.forEach(function(func) {
func(); // outputs the number '10' ten times
});

It outputs the number 10 ten times in a row. The variable i has a value of 10 once the loop completes, and so when console.log(i) is called, that value prints each time.

To fix this problem, developers use immediately-invoked function expressions (IIFEs) inside of loops to force a new copy of the variable they want to iterate over to be created, as in this example:

var funcs = [];for (var i = 0; i < 10; i++) {
funcs.push((function(value) {
return function() {
console.log(value);
}
}(i)));
}
funcs.forEach(function(func) {
func(); // outputs 0, then 1, then 2, up to 9
});

**Fortunately, block-level binding with let and const in ECMAScript 6 can simplify this loop for you.

Let Declarations in Loops:

On each iteration, the loop creates a new variable and initializes it to the new value with the previous same name. Consider the example:

var funcs = [];for (let i = 0; i < 10; i++) {
funcs.push(function() {
console.log(i);
});
}
funcs.forEach(function(func) {
func(); // outputs 0, then 1, then 2, up to 9
})

For more clearance about the fact follow this example also:

var funcs = [],
object = {
a: true,
b: true,
c: true
};
for (let key in object) {
funcs.push(function() {
console.log(key);
});
}
funcs.forEach(function(func) {
func(); // outputs 'a', then 'b', then 'c'
});

In this example, the for-in loop shows the same behavior as the for loop. Each time through the loop, a new key binding is created, and so each function has its own copy of the key variable. The result is that each function outputs a different value. If var were used to declare key, all functions would output “c”.

Constant Declarations in Loops:

The ECMAScript 6 specification doesn’t explicitly disallow const declarations in loops; however, there are different behaviors based on the type of loop you’re using. For a normal for loop, you can use const in the initializer, but the loop will throw a warning when you attempt to change the value. For example:

var funcs = [];// throws an error after one iteration
for (const i = 0; i < 10; i++) {
funcs.push(function() {
console.log(i);
});
}

In this code, the i variable is declared as a constant. The first iteration of the loop, where i is 0, executes successfully. An error is thrown when i++ executes because it’s attempting to modify a constant.

When used in a for-in or for-of loop, on the other hand, a const variable behaves the same as a let variable. So the following should not cause an error:

var funcs = [],
object = {
a: true,
b: true,
c: true
};
// doesn’t cause an error
for (const key in object) {
funcs.push(function() {
console.log(key);
});
}
funcs.forEach(function(func) {
func(); // outputs 'a', then 'b', then 'c'
});

The for-in and for-of loops work with const because the loop initializer creates a new binding on each iteration through the loop rather than attempting to modify the value of an existing binding (here the key is a, b, and c).

Global Block Bindings:

Another way in which let and const are different from var. When var is used in the global scope, which is a property on the global object (window in browsers). That means you can overwrite an existing global using var, such as:

// in a browser
var RegExp = 'Hello!';
console.log(window.RegExp); // 'Hello!'
var ncz = 'Hi!';
console.log(window.ncz); // 'Hi!'

If you instead use let or const in the global scope, a new binding is created in the global scope but no property is added to the global object. That also means you cannot overwrite a global variable using let or const, you can only shadow it. Here’s an example:

// in a browser
let RegExp = 'Hello!';
console.log(RegExp); // 'Hello!'
console.log(window.RegExp === RegExp); // false
const ncz = 'Hi!';
console.log(ncz); // 'Hi!'
console.log('ncz' in window); // false

This capability makes let and const a lot safer to use in the global scope when you don’t want to create properties on the global object

JavaScript Functions

What is a Function?

A function is a group of statements that perform specific tasks and can be kept and maintained separately from the main program. Functions provide a way to create reusable code packages that are more portable and easier to debug. Here are some advantages of using functions:

  • Functions reduce the repetition of code within a program — Function allows you to extract commonly used block of code into a single component. Now you can perform the same task by calling this function wherever you want within your script without having to copy and paste the same block of code again and again.
  • Functions make the code much easier to maintain — Since a function created once can be used many times, so any changes made inside a function automatically implemented at all the places without touching the several files.
  • Functions make it easier to eliminate the errors — When the program is subdivided into functions if any error occurs you know exactly what function causing the error and where to find it. Therefore, fixing errors becomes much easier.

The following section will show you how to define and call functions in your scripts.

Defining and Calling a Function

The declaration of a function starts with the function keyword, followed by the name of the function you want to create, followed by parentheses i.e. () and finally, place your function's code between curly brackets {}. Here's the basic syntax for declaring a function:

// Defining function
function sayHello() {
alert("Hello, welcome to this website!");
}

// Calling function
sayHello(); // 0utputs: Hello, welcome to this website!

Once a function is defined it can be called (invoked) from anywhere in the document, by typing its name followed by a set of parentheses, like sayHello() in the example above.

Note: A function name must start with a letter or underscore character not with a number, optionally followed by more letters, numbers, or underscore characters. Function names are case sensitive, just like variable names.

Adding Parameters to Functions

You can specify parameters when you define your function to accept input values at run time. The parameters work like placeholder variables within a function; they’re replaced at run time by the values (known as argument) provided to the function at the time of invocation.

The displaySum() function in the following example takes two numbers as arguments, simply add them together, and then display the result in the browser.

// Defining function
function displaySum(num1, num2) {
var total = num1 + num2;
alert(total);
}

// Calling function
displaySum(6, 20); // 0utputs: 26
displaySum(-5, 17); // 0utputs: 12

You can define as many parameters as you like. However, for each parameter you specify, a corresponding argument needs to be passed to the function when it is called, otherwise, its value becomes undefined. Let's consider the following example:

// Defining function
function showFullname(firstName, lastName) {
alert(firstName + " " + lastName);
}

// Calling function
showFullname("Clark", "Kent"); // 0utputs: Clark Kent
showFullname("John"); // 0utputs: John undefined

Default Values for Function Parameters ES6

With ES6, now you can specify default values to the function parameters. This means that if no arguments are provided to the function when it is called these default parameter values will be used. This is one of the most awaited features in JavaScript. Here’s an example:

function sayHello(name = 'Guest') {
alert('Hello, ' + name);
}
sayHello(); // 0utputs: Hello, Guest
sayHello('John'); // 0utputs: Hello, John

While prior to ES6, to achieve the same we had to write something like this:

function sayHello(name) {
var name = name || 'Guest';
alert('Hello, ' + name);
}
sayHello(); // 0utputs: Hello, Guest
sayHello('John'); // 0utputs: Hello, John

Returning Values from a Function

A function can return a value back to the script that called the function, as a result, using the return statement. The value may be of any type, including arrays and objects.

The return the statement usually placed as the last line of the function before the closing curly bracket and ends it with a semicolon, as shown in the following example.

// Defining function
function getSum(num1, num2) {
var total = num1 + num2;
return total;
}

// Displaying returned value
alert(getSum(6, 20)); // 0utputs: 26
alert(getSum(-5, 17)); // 0utputs: 12

A function can not return multiple values. However, you can obtain similar results by returning an array of values, as demonstrated in the following example.

// Defining function
function divideNumbers(dividend, divisor){
var quotient = dividend / divisor;
var arr = [dividend, divisor, quotient];
return arr;
}

// Store returned value in a variable
var all = divideNumbers(10, 2);

// Displaying individual values
alert(all[0]); // 0utputs: 10
alert(all[1]); // 0utputs: 2
alert(all[2]); // 0utputs: 5

Working with Function Expressions

The syntax that we’ve used before to create functions is called function declaration. There is another syntax for creating a function that is called a function expression.

// Function Declaration
function getSum(num1, num2) {
var total = num1 + num2;
return total;
}

// Function Expression
var getSum = function(num1, num2) {
var total = num1 + num2;
return total;
};

Once function expression has been stored in a variable, the variable can be used as a function:

var getSum = function(num1, num2) {
var total = num1 + num2;
return total;
};

alert(getSum(5, 10)); // 0utputs: 15

var sum = getSum(7, 25);
alert(sum); // 0utputs: 32

The syntax of the function declaration and function expression looks very similar, but they differ in the way they are evaluated, check out the following example:

declaration(); // Outputs: Hi, I'm a function declaration!
function declaration() {
alert("Hi, I'm a function declaration!");
}

expression(); // Uncaught TypeError: undefined is not a function
var expression = function() {
alert("Hi, I'm a function expression!");
};

As you can see in the above example, the function expression threw an exception when it was invoked before it is defined, but the function declaration executed successfully.

JavaScript parse declaration function before the program executes. Therefore, it doesn’t matter if the program invokes the function before it is defined because JavaScript has hoisted the function to the top of the current scope behind the scenes. The function expression is not evaluated until it is assigned to a variable; therefore, it is still undefined when invoked.

Understanding the Variable Scope

However, you can declare the variables anywhere in JavaScript. But, the location of the declaration determines the extent of a variable’s availability within the JavaScript program i.e. where the variable can be used or accessed. This accessibility is known as variable scope.

By default, variables declared within a function have the local scope that means they cannot be viewed or manipulated from outside of that function, as shown in the example below:

// Defining function
function greetWorld() {
var greet = "Hello World!";
alert(greet);
}

greetWorld(); // Outputs: Hello World!

alert(greet); // Uncaught ReferenceError: greet is not defined

However, any variables declared in a program outside of a function have global scope i.e. it will be available to all script, whether that script is inside a function or outside. Here’s an example:

var greet = "Hello World!";

// Defining function
function greetWorld() {
alert(greet);
}

greetWorld(); // Outputs: Hello World!

alert(greet); // Outputs: Hello World!

--

--