Hello friends,
As you may know, after 6 years of seemingly suspended from the ES5 release in 2009, in June 2015, there was an important update of JavaScript that brought a lot of new features. Since that time, every year we have received a new version with a series of new features that are supposed to bring a lot of benefits and efficiency in the developer work. So far, ES12 or ES2021 is about to release new features, along with that ES11 is an old version. That is enough for us to feel that the methods and ways of operation change and upgrade dramatically. So have you used all of those features? Then in this article, we will take turns going through the features before the end of 2020! Let’s go
ES6 (ECMAScript 2015)
1. Arrow functions (=>)
1 2 3 4 5 6 7 8 9 10 11 12 | // traditional function expression var numbers = [2, 6, 40]; var twiceNum = numbers.map(function(number) { return number*2 }) // arrow functional var numbers = [2, 6, 40]; var twiceNum = numbers.map((number) => number*2); // lexical this var greenBtn = document.getElementById(‘greenBtn’); greenButton.addEventListener(‘click’, function() { this.style.backgroundColor = “red”; // no more binding }) |
2. Classes
1 2 3 4 5 6 7 8 9 10 11 12 | // Class class Person { constructor(firstName, lastName, age) { this.firstName = firstName; this.lastName = lastName; this.age = age; } sayHi() { return ‘Hi, my name is ${firstName}. Nice to meet you.’; } } |
3. Template strings
1 2 3 4 5 6 | var name = ‘Peter’, city = ‘London’; // Before ES6 var greeting = "Hello, my name is " + name + ". I am from " + city + "."; // After ES6 var greeting = ‘Hello, my name is ${name}. I’m from ${city}.‘ |
4. Let and Const
1 2 3 4 5 6 7 8 9 10 11 | // Let — variable is available only in the block of code function calculate(x) { var y = 0; if (x > 10) { // let y is only available in this block of code let y = 30; return y; } return y; } |
5. Promises
1 2 3 4 5 6 | const checkResult = () => new Promise(resolve, reject) => { setTimeout(resolve, 500)} checkResult() .then((result) => { console.log(result); }) .catch((error) => { console.log(error); }) |
ES7 (ECMAScript 2016)
1. Array.prototype.includes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var fruits = ['banana', 'apple', 'grape', 'nut', 'orange']; var favoriteFruit = 'banana'; // Before ES7 function isFruit(fruit) { if (fruits.indexOf(fruit) !== -1) { return true; } else { return false; } } isFruit(favoriteFruit); // returns true // After ES7 fruits.includes(favoriteFruit); // returns true |
2. Exponentiation Operator
1 2 3 4 5 6 7 8 9 10 11 12 | // Before ES7 (loop case) function calculate(num, exponent) { var res = 1; for (var i = 0; i < exponent; i++) { res *= num; } return res; } // After ES7 const calculate = (num, exponent) => num ** exponent; |
ES8 (ECMAScript 2017)
1. Object.values () and Object.entries ()
1 2 3 4 5 6 7 8 9 10 11 12 13 | var person = { name: ‘Jenny’, age: 24, country: ‘UK’, city: ‘London’, } // Object.values() var arrJenny = Object.values(person); // returns [‘Jenny’, 24, ‘UK’, ‘London’]; // Object.entries() var arrJennyEntries = Object.entries(person); // returns |
2. String.prototype.padEnd () and String.prototype.padStart ()
1 2 3 4 5 6 7 | var string = ‘Alice’; // padStart() — we assume our string needs to have 10 characters string.padStart(10, ‘o’); // returns ‘oooooAlice’ // padEnd() string.padEnd(10, ‘o’); // returns ‘Aliceooooo’; |
3. Async function (async / await)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function delayResult() { return new Promise(resolve => { setTimeout(() => { resolve(‘Done’); }, 5000) }) } async function getResult() { var result = await delayResult(); return result; } getResult(); |
ES9 (ECMAScript 2018)
1. Asynchronous iteration
1 2 3 4 | for await (let book of books) { console.log(book) }; |
2. Rest operator
1 2 3 4 5 6 7 8 9 | const fruits = { orange: 1, apple: 10, banana: 4, } const { orange, …rest } = fruits; console.log(rest); // { apple: 10, banana: 4 }; // in the function function getFruits(apple, …rest) { return rest.banana; } |
3. Promise.prototype.finally
1 2 3 4 5 6 | const checkResult = () => new Promise(resolve, reject) => {setTimeout(resolve, 500)} checkResult() .then((result) => { console.log(result); }) .catch((error) => { console.log(error); }) .finally(() => { console.log(‘Promise finished!’) }) |
ES10 (ECMAScript 2019)
1. Optional Catch Binding
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // Before ES10 try { doSomethingThatMightThrow(); } catch (exception) { // ^^^^^^^^^ // We must name the binding, even if we don’t use it! handleException(); } // After ES10 try { doSomethingThatMightThrow(); } catch { // → No binding! handleException(); } |
2. Object.fromEntries ()
1 2 3 4 5 6 7 8 9 10 | const entries = new Map([ ['foo', 'bar'], ['baz', 42] ]); const obj = Object.fromEntries(entries); console.log(obj); // expected output: Object { foo: "bar", baz: 42 } |
3. Array.flat ()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var arr1 = [1, 2, [3, 4]]; arr1.flat(); // [1, 2, 3, 4] var arr2 = [1, 2, [3, 4, [5, 6]]]; arr2.flat(); // [1, 2, 3, 4, [5, 6]] var arr3 = [1, 2, [3, 4, [5, 6]]]; arr3.flat(2); // [1, 2, 3, 4, 5, 6] var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]; arr4.flat(Infinity); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] |
4. Array.flatMap ()
1 2 3 4 5 6 7 8 | let arr1 = ["it's Sunny in", "", "California"]; arr1.map(x => x.split(" ")); // [["it's","Sunny","in"],[""],["California"]] arr1.flatMap(x => x.split(" ")); // ["it's","Sunny","in", "", "California"] |
5-6. String.trimStart () & String.trimEnd ()
String.trimStart ()
1 2 3 4 5 6 7 8 | var greeting = ' Hello world! '; console.log(greeting); // expected output: " Hello world! "; console.log(greeting.trimStart()); // expected output: "Hello world! "; |
String.trimEnd ()
1 2 3 4 5 6 7 8 | var greeting = ' Hello world! '; console.log(greeting); // expected output: " Hello world! "; console.log(greeting.trimEnd()); // expected output: " Hello world!"; |
7. globalThis Object
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | const global = Function('return this')(); const getGlobal = function () { if (typeof self !== 'undefined') { return self; } if (typeof window !== 'undefined') { return window; } if (typeof global !== 'undefined') { return global; } throw new Error('unable to locate global object'); } const global = getGlobal(); // will return window object in the browser // array usage example const numbers = new global.Array(1, 2, 3); console.log(numbers); // outputs [1, 2, 3]; |
ES11 (ECMAScript 2020)
1. Nullish coalescing
First mention the nullish coalescing or operator ??
. According to the definition of MDN, ??
is a logical operator that will return the right side if the left side is null or undefined. So you can use it to short-circuit like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 | function a() { return null } function b() { return 1 } function c() { return 2 } console.log(a() ?? c()) // 2 console.log(b() ?? c()) // 1 |
1. Optional Chaining?
In the past, accessing the object’s keys would fail if the key didn’t exist, or it is better to first check if the key exists or not. But with ES11, you can handle it simply by operator?.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | const player = { details: { name: { firstName: "Quang", lastName: "Hai", age: 20 } }, jobs: [ "dev js", "dev php" ] } const playerFirstName = player?.details?.name?.firstName; |
2. Private fields
By prefixing the property or method with #, they will only be accessible from within the class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class Foo { #b = 15; a = 10; get() { return this.#b; } increment() { ++this.#b; } } const obj = new Foo(); obj['#b']; // undefined obj.a = 10; obj.hasOwnProperty('#b'); // false |
3. BigInt
BigInt is a new built-in object introduced in ES11, used to represent integers greater than 2 ^ (53) –1. In Javascript, there is a Number object, but it is limited in a narrow scope, so BigInt was born to solve this problem.
Take a look at Number’s value limit:
1 2 3 4 5 6 7 8 | console.log(Number.MAX_SAFE_INTEGER); //9007199254740991 const max = Number.MAX_SAFE_INTEGER; console.log(max +1); //9007199254740992 -> Correct value! console.log(max +10); //9007199254741000 -> Incorrect value! (1001) |
In the third example the data is too large, so we can solve it by using BigInt instead.
1 2 3 4 5 6 7 8 9 10 | const myBigNumber = 9007199254740991n; console.log(myBigNumber +1n); //9007199254740992n -> Correct value! console.log(myBigNumber +10n); //9007199254741001n -> Correct value! //Note: console.log(myBigNumber +10); //Error: you cannot mix BigInt and other types, use explicit //conversions. //Correct way: You have to add the letter 'n' on the end of the //number |
Conclude
Although it is a conclusion, but there are some more features of ES6 to ES11 that I have not listed all here, please learn more. Since ES7 onwards, the updates are only minor additions, completely different from ES6, so it’s very easy to upgrade knowledge. Please welcome my next article.
Thank you !