DEV Community

Cover image for Introduction to Modern JavaScript
Kashu_happy
Kashu_happy

Posted on • Edited on

Introduction to Modern JavaScript

Today, JavaScript is one of the most widely used programming languages on the planet. It may be used to create online or mobile applications, as well as command-line utilities. The ECMAScript 6 (ES 6) standard, which was introduced in 2015 and includes numerous new capabilities for JavaScript, is used in modern JavaScript.

ECMAScript

The European Computer Manufacturers Association (ECMA) is a standard for scripting languages such as JavaScript. Most of the time, these specs add new features to the language that improve the development experience.

Let's have a look at some of the significant changes brought about by the new ECMAScript version.

Variable Declaration

To declare a variable in JavaScript, there are three keywords available, each with its own set of peculiarities. var, let, and const are the three variables. Prior to ES6, there were only two types of scopes in JavaScript: Global Scope and Function Scope. With the ES6 version, the keywords "let" and "const" were added. In JavaScript, these two keywords give block scope variables and constants. The table below shows if these three variables can be reassigned, mutated, and the type of scope:

Explanation of how variables are reassigned, mutated, and type of scope.

  • var declared variables are also hoisted during execution, which means they are pushed to the top of the scope. The following code, for example,
console.log(myNum); // `undefined`
var myNum = 5;
Enter fullscreen mode Exit fullscreen mode

is interpreted as follows during execution:

var myNum;
console.log(myNum); // `undefined`
myNum = 5;
Enter fullscreen mode Exit fullscreen mode

When a variable is defined using the var keyword in a function, it is function scoped, which means that it may be accessed by everything in that function. A function scoped variable generated within a function, on the other hand, cannot be accessed outside of that function. For example:

function myFunc () {
   var myFunc = 'Mary';
   console.log(myFunc); // `Mary`
}
myFunc();
console.log(myFunc); // [Function: myFunc] 
// myFunc can not be accessed in the outermost scope of the function.
Enter fullscreen mode Exit fullscreen mode
  • let - the assignment of let and const variables is also hoisted, but not their declarations. It may appear that there is no hoisting since they are designed to not be employed prior to assignation, but there is. Furthermore, a let variable cannot be re-declared:
let num = 2;
let num = 8; // Syntaxerror
Enter fullscreen mode Exit fullscreen mode

Let's look at how block-scoping affects our prior example using let:

function myFunc() {
    let myFunc = 'Mary';
    if (true) {
        let myFunc = 'Joh';
        console.log(myFunc); // 'Joh' 
        // a new variable myFunc has been created
        // the variable can not be accessed outside this scope
    }
    console.log(myFunc); // 'Mary'
    // the if statement does not affect this value since it is in a different scope
}
myFunc();
console.log(myFunc); // [Function: myFunc]
// myFunc can not be accessed in the outermost function
Enter fullscreen mode Exit fullscreen mode
  • const - variables can not be re-declared
const name = 'Mary';
const name = 'John'; // SyntaxError
Enter fullscreen mode Exit fullscreen mode

Re-assignment is also not allowed with const

const name = 'Mary';
name = 'John'; // raises an error
Enter fullscreen mode Exit fullscreen mode

Const variables, in a nutshell:

  1. Before being assigned, it is not possible to access it.
  2. It is not possible to declare it again in the same scope.
  3. Are block scoped
  4. Reassignment is not possible.

const variables are not immutable, as we well know. It does, however, imply that variables in an array or object marked as const can be mutated.

In the case of arrays:

const person = [];
person.push('Mary'); // variable is mutated but not reassigned
console.log(person[0]); // 'Mary' 
person = ['Roy']// TypeError. Reassignment not allowed
Enter fullscreen mode Exit fullscreen mode

In the case of objects:

const person = {
  name: 'Mary'
};
person.name = 'Roy' // variable is mutated and not completely reassigned.
console.log(person.name) //
person = "Sandra" // TypeError. Reassignment not allowed
Enter fullscreen mode Exit fullscreen mode

Arrow Function

Functions in JavaScript can be defined in the following ways:

// Method 1
function add1(a, b) {
    return a + b; // explicit return
}

// Method 2
let add2 = (a, b) => {
    return a + b;
}

let add3 = (a, b) => a + b; // implicit return

console.log(add1(2,3)); 
console.log(add2(4,5)); 
console.log(add3(6,7));
Enter fullscreen mode Exit fullscreen mode

Output:

5
9
13
Enter fullscreen mode Exit fullscreen mode

The first method is the standard JavaScript way for defining functions. The arrow function, which was introduced in ES6, is the alternative method 2.
The following are some of the benefits of employing arrow functions:

  • enables us to define more concise function syntax with implicit return as seen above.

When the return keyword is used in the body of a function, it is called an explicit return. You can use implicit return with arrow functions, which means you do not have to use the return keyword to return a value.

  • this is a result of the surrounding.

Because this is equal to the this value of the surrounding execution environment, you don't need to use the "that = this" technique before executing a function within a function when using arrow functions.

function myFunc() {
    this.num = 5;
    setTimeout(() => {
      this.num++;
      console.log(this.num) // 6
    }, 0);
  }
myFunc();
Enter fullscreen mode Exit fullscreen mode

You can eliminate the parentheses surrounding your function if it just accepts only one parameter. For instance, have a look at the code below,

const mul = (x) => x * 2;
Enter fullscreen mode Exit fullscreen mode

without the use of parentheses:

const mul = x => x * 2;
Enter fullscreen mode Exit fullscreen mode

Object handling

If the variable name is the same as the property name, you can perform the following when assigning a variable to an object property:

const num = 10;
const myObj = { num };
console.log(myObj.num);
Enter fullscreen mode Exit fullscreen mode

Output:

10
Enter fullscreen mode Exit fullscreen mode

Before ES6, code was written like this when you wanted to define a new object literal and utilize variables as object property values:

const num1 = 10;
const num2 = 20;

const myObj = {
  num1: num1,
  num2: num2,
};

console.log(myObj.num1)
console.log(myObj.num2)
Enter fullscreen mode Exit fullscreen mode

Output:

10
20
Enter fullscreen mode Exit fullscreen mode

Because the names of the properties of myObj are the same as the variable names, this is somewhat redundant. Therefore, when the variable name and the property name are the same in ES2015, you may use the following syntax:

const num1 = 20;
const num2 = 30;

const myObj = {
  num1,
  num2,
};

console.log(myObj.num1) 
console.log(myObj.num2)
Enter fullscreen mode Exit fullscreen mode

Output:

20
30
Enter fullscreen mode Exit fullscreen mode
Object.freeze() method

This technique is used to freeze an item. This indicates that if we apply this method on an object, we will not be able to update or tamper with it.

let person = {
    name: 'Mary',
    contacts: {
        mobile: '123',
        home: '456'
    }
}
Object.freeze(person);

person.name = 'Nick';
console.log(person);

person.contacts.mobile = '789';
console.log(person);
Enter fullscreen mode Exit fullscreen mode

Output:

{ name: 'Mary', contacts: { mobile: '123', home: '456' } }
{ name: 'Mary', contacts: { mobile: '789', home: '456' } }
Enter fullscreen mode Exit fullscreen mode

I tried to set a new value to the "name" property after using the ".freeze()" method on the object, but as the output indicates, it is unaffected. However, even though I used the ".freeze()" method to provide a new value to the "mobile" field of the "contacts" object, it was assigned. This is because when the ".freeze()" function is used to an object, it only freezes the object's first-level value. That is, it has no effect on items on the second or inner levels.


Promises

In JavaScript, promises are the most prevalent approach to handle asynchronous tasks. Developers utilized callbacks to manage asynchronous activities before promises. As a result, many callbacks within callbacks were constructed, eventually leading to "The Callback Hell."

A promise established in JavaScript is primarily built on the idea that when the time comes, it will either be resolved or rejected. A promise exists in the following three states:

  • Fulfilled - the promised task was completed successfully.

  • Rejected - the promised task was not completed or is unsuccessful.

  • Pending - the promised task has neither been fulfilled nor rejected.

In a basic JavaScript example, let's utilize Promises.

function work() {
    return true;
}
const myPromise = new Promise((resolve, reject) => {
    let isopen = work();

    if(isopen === true) {
        resolve('Shop is open!')
    }
    else {
        reject('Shop is closed now!')
    }
});

myPromise.then((order) => {
    console.log(order);
}).catch((order) => {
    console.log(order);
});
Enter fullscreen mode Exit fullscreen mode

Output:

Shop is open!
Enter fullscreen mode Exit fullscreen mode

As you can see, I've generated a promise called "myPromise" with two parameters: one for success (resolve) and one for failure (reject). The return value of the "work()" function is sent to the "isopen" variable.

The result of the "task()" function is always "true." As a result, the Promise will verify the condition and, if it is true, resolve the Promise; else, it will be rejected. When we use the Promise, the "then()" function is invoked once the Promise has been resolved. Then we may determine what to do with the Promise that has been resolved. However, if the Promise fails, we must call the "catch()" function. In this case, it fulfilled the promise's requirement, and as a consequence, Promise will be resolved.


Classes

A JavaScript class is just a template for constructing objects. Because JavaScript is a prototype-based language, ES6 has introduced JavaScript classes as a prototype inheritance with syntactic sugar rather than a new class-based inheritance mechanism. If you are familiar with the C# or Java programming languages, you are probably already aware of the concept of classes.

Prototype syntax prior to ES6:

var User = function(name, age) {
    this.name = name;
    this.age = age;
  }
  User.prototype.stringSentence = function() {
    return "Hello, my name is " + this.name + " and I'm " + this.age;
  }
  var newUser = new User("Mary", 20);
  console.log(newUser.name)
  console.log(newUser.age)
  console.log(newUser.stringSentence());
Enter fullscreen mode Exit fullscreen mode

Output:

Mary
20
Hello, my name is Mary and I'm 20
Enter fullscreen mode Exit fullscreen mode

The following is the syntax for ES6 classes:

class User {
    constructor(name, age) {
      this.name = name;
      this.age = age;
    }
    stringSentence() {
      return `Hello, my name is ${this.name} and I am ${this.age}`;
    }
  }
  const newUser = new User("Kim", 25);
  console.log(newUser.name)
  console.log(newUser.age)
  console.log(newUser.stringSentence()) 
Enter fullscreen mode Exit fullscreen mode

Output:

Kim
25
Hello, my name is Kim and I am 25
Enter fullscreen mode Exit fullscreen mode

That brings me to the end of my article; I hope you enjoyed it. Happy Coding 👨‍💻!

Top comments (1)

Collapse
 
samy_muchiri profile image
Sammy Muchiri

Nice work