Summary of features of each version of ECMA

(When you are lucky, think of bad luck, and don't get too complacent; when you are unlucky, think of good luck, and don't be downcast. Always keep a balanced mind and stable emotions. This is also the way to live longer...——Ji Xianlin)

insert image description here

ECMA

ecma official website
ecma github version record
w3schools
ECMAScript is a standardized specification of a scripting language developed by Brandon Edge of Netscape; originally named Mocha, later renamed LiveScript, and finally renamed JavaScript. In December 1995, Sun and Netscape jointly published JavaScript. In November 1996, Netscape submitted JavaScript to the European Computer Manufacturers Association for standardization. The first version of ECMA-262 was adopted by the Ecma organization in June 1997. ECMA Script is the name of the scripting language standardized by ECMA-262. Although JavaScript and JScript are compatible with ECMAScript, they contain functionality beyond ECMAScript.

ecma has been named after the year since 2016, and the old es versions are named after numbers, such as ES5 (2009) and ES6 (2015)
But you can still use numbers

Version years
ES2009 Or ES5 June 2009
ES2015 Or ES6 June 2015
ES2016 Or ES7 June 2016
ES2017 Or ES8 June 2017
ES2018 Or ES9 June 2018
ES2019 Or ES10 June 2019
ES2020 Or ES11 June 2020
ES2021 Or ES12 June 2021
ES2022 Or ES13 June 2022

The following are the commonly used features in development. Some authors think that the features that are not commonly used may not be recorded or recorded in detail.

ES13

Released June 2022

1. await and async release strong binding

await no longer has to be written in async. In the past, we usually wrote it as follows.

 import posts from './posts';

 const getPosts = async() => {
    
    
   let posts = await posts();
   return posts;
 }

In es13, we can do this directly.

let posts = await posts();

Removing the strong binding with async has the following benefits

  1. Dynamic dependency paths
    await helps to load or import messages at runtime when you have dynamic paths that depend on runtime values.
const messages = await import(`./messages-${
      
      language}.js`);
  1. Dependency fallback
    If an imported module fails to load, the loaded fallback module is used to load dependencies.
let lodash;
 try {
    
    
   lodash = await import('https://first.domain.com/lodash');
 } catch {
    
    
   lodash = await import('https://second.domain.com/lodash');
 }
  1. Resource Initialization
    This feature can be used to initialize an application with a database.
import {
    
     dbConnector} from './dbUtils.js'
//connect to database
const connection = await dbConnector.connect();
export default function(){
    
     
  connection.list()
}
  1. It is not returned as a promise type itself, but internal business code processing needs to use await

2. Support private properties and methods

In the past, we often used typescript private to write private properties and methods of classes, but because there are no strict restrictions when using js, special naming is required for marking, such as adding an underscore _ before the variable name. But because the check is not enforced, it may lead to business errors.

 class Employee  {
    
    
 
 constructor() {
    
    
   this.name = "John"; //public
   this._age=35; //private
 }

 const employee = new Employee();
 employee.name = "Jack";
 employee._age =35; //No error

Now, es13 natively supports public and private property methods, improving the scalability and maintainability of js code.
Mark a variable as a private property or method by prefixing it with a # sign.
In the example below, the Employee class has been defined with private variables outside the constructor.

class Employee  {
    
    
   name = "John";
   #age=35;
  constructor() {
    
    
   }

   #getAge() {
    
    
     return #age
   }
 
}

 const employee = new Employee();
 employee.name = "Jack";
 employee.#age = 35; // Throws an error

And also supports static fields and methods. Just add the static tag in front.

class Employee{
    
    
  name = "John";
  static #employerName="Github"

  static #getEmployerName() {
    
    
    return #employerName
  }
}
const employee = new Employee();
employee.emp = "Jack";
employee.#employerName = 35; // Throws an error

3. Array at() method

The .at() method is used to access array or string elements by passing negative index values. That is, it allows accessing values ​​from the end of an array or from a string.
Before ES2022, you should have to access elements from the end, like this.

const array = [1, 2, 3, 4, 5];
console.log(array[array.length - 2]); //4
console.log(array.slice(-2)[0]); //4

const string = '12345';
console.log(string[string.length - 2]); // '4'
console.log(string.slice(-2)[0]); // '4'

Now you should be able to write.

const array = [1, 2, 3, 4, 5];
console.log(array.at(-2)); // 4

const string = '12345';
console.log(string.at(-2));

4. Custom error reasons

In the example below, let's catch an error from JSON processing and rethrow it with a new meaningful message along with the original reason for the error.

function processUserData(arrayData) {
    
    
   return arrayData.map(data => {
    
    
       try {
    
    
         const json = JSON.parse(data);
         return json;
       } catch (err) {
    
    
         throw new Error(
           `Data processing failed`,
           {
    
    cause: err}
         );
       }
     });
 }

5. Object.hasOwn()

The new Object.hasOwn() method replaces Object.prototype.hasOwnProperty. It is a static method, which is more concise than hasOwnProperty and solves some problems of hasOwnProperty.

If you create a new object with the help of create(null) function, then the newly created object does not inherit from Object.prototype. So it doesn't have hasOwnProperty method.
Let's take an example to verify hasOwnProperty on objects created with the create(null) function.

const user = Object.create(null);
user.age = 35;
user.hasOwnProperty('age'); // throws a TypeError

In this case, you can use the hasOwn() method to determine own properties.

 const user = Object.create(null);
 user.age = 35;
 user.hasOwn('age'); // true

6. Regular expression matching index

Regular expression matching has been upgraded to include more information about matching groups. \d Additional information includes the start and end index of the match in RegExp using flags in the input string.

ES12

Released in mid-2021

1. replaceAll()

The new replaceAll() method in prototype String is used to replace all occurrences of a string from another string value. Earlier, it was not possible to replace all instances of a substring without using regular expressions.
Before ES2021

 console.log('10101010'.replace(new RegExp('0', 'g'), '1')); // 11111111
 console.log('01010101'.replace(/0/g, '1')); // 11111111

After ES2021

 console.log('10101010'.replaceAll('0', '1')); // 11111111
 console.log('01010101'.replaceAll('0', '1')); // 11111111

2. promise.any

The array of promises passed in, the one that succeeds first will be processed as the return value. An exception is thrown if all fails.

let promise1 = new Promise((resolve) => setTimeout(resolve, 100, 'Resolves after 100ms'));
let promise2 = new Promise((resolve) => setTimeout(resolve, 200, 'Resolves after 200ms'));
let promise3 = new Promise((resolve, reject) => setTimeout(reject, 0) );

let promises = [promise1, promise2, promise3];

 Promise.any(promises)
     .then( value => console.log(value)); // Resolves after 100ms
 (async () => {
    
    
   try {
    
    
     const output = await Promise.any([
       Promise.reject('Error 1'),
       Promise.reject('Error 2'),
       Promise.reject('Error 3'),
     ]);
     console.log(`Output: ${
      
      output}`);
   } catch (err) {
    
    
     console.log(`Error: ${
      
      err.errors}`);
   }
 })(); 
 // Error: Error1,Error2,Error3

3. Weak citations

WeakRef provides two new functions

  1. Use the WeakRef class to create weak references to objects
  2. Run user-defined finalizers after objects are garbage collected, using the FinalizationRegistry class
    Prior to ES12, WeakMaps and WeakSets were the only way to weakly reference objects in JavaScript. The WeakRef in ES12 provides the actual weak reference, which opens a window into the life cycle of the object.
const myObject = new WeakRef({
    
    
  name: ‘Sudheer’,
  age: 34
});
console.log(myObject.deref()); //output: {name: “Sudheer”, age: 35}
console.log(myObject.deref().name); //output: Sudheer

The object FinalizationRegistry allows you to request a callback when the object is garbage collected. It is used as a cleanup callback.

// Create new FinalizationRegistry:
const reg = new FinalizationRegistry((val) => {
    
    
  console.log(val);
});

(() => {
    
    
// Create new object:
  const obj = {
    
    }

// Register finalizer for the "obj" as first argument and value for callback function as second argument:
  reg.register(obj, 'obj has been garbage-collected.')
})();

4. Number separator

Number separators facilitate the reading of large numbers (or number literals) in JavaScript by providing separation between numbers using an underscore (_). In other words, number literals are more readable by creating a visual separation between groups of numbers.

5. Logical operators

Logical assignment operators combine logical operators (&&, ||, or ??) with assignments. They are useful for assigning default values ​​to variables.
&&=: For example, the following code.

 x = x && (x = y); 
 (OR)
 if (x) {
    
    
   x = y;
 }

In es12 it can be optimized as

 let x = 10;
 let y = 20;
 x &&= y;
 console.log(x); // 20

||=: such as the following code

 x = x || (x = y); 
 (OR)
 if (!x) {
    
    
   x = y;
 }

can be optimized to

 let x = 0;
 let y = 20;
   x ||= y;
 console.log(x); // 20

??=: For example, the following code.

  x ?? (x = y);
  (OR)
  if (!x) {
    
    
    x = y;
  }

can be optimized to

 let x;
 let y = 1;
 x ??= y;
 console.log(x); // 1

ES11

June 2020

1. Large integer

In earlier JavaScript versions, the use of the Number type was limited. Number ie, you cannot safely represent integer values ​​(primitive values) larger than pow(2, 53) .
In ES2020,

BigInt was introduced as the 7th primitive type to represent integers (integers with arbitrary precision) greater than pow(2, 53) - 1 (or 9007199254740991 or Number.MAX_SAFE_INTEGER).

// 1. Current number system
const max = Number.MAX_SAFE_INTEGER;
console.log(max + 1) // 9007199254740992
console.log(max + 2) // 9007199254740992

// 2. BigInt representation
const bigInt = 9007199254740991n;
const bigIntConstructorRep = BigInt(9007199254740991); // 9007199254740991n
const bigIntStringRep = BigInt("9007199254740991"); // 9007199254740991n

// 3. Typeof usage

console.log(typeof 1)// number
console.log(typeof 1n)// bigint
console.log(typeof BigInt('1'))// bigint

// 4. Operators

const previousMaxNum = BigInt(Number.MAX_SAFE_INTEGER);
console.log(previousMaxNum + 2n); //9007199254740993n (this was not possible before)
console.log(previousMaxNum -2n); //9007199254740990n
console.log(previousMaxNum * 2n); //18014398509481982n
console.log(previousMaxNum % 2n); //1n
console.log(previousMaxNum / 2n); // 4503599627370495n

// 5. comparison
console.log(1n === 1); // false
console.log(1n === BigInt(1)); // true
console.log(1n == 1); // true

2. Dynamic import

The new function dynamic import was introduced for conditional or on-demand loading of modules. Since it returns a promise of the module namespace object of the requested module, the module can be resolved or the import can now be assigned to a variable using async/await as follows

<script>
const moduleSpecifier = './message.js';
import(moduleSpecifier)
  .then((module) => {
    
    
    module.default(); // Hello, default export
    module.sayGoodBye(); //Bye, named export
  })
  .catch(err => console.log('loading error'));
</script>
<script>
(async function() {
    
    
  const moduleSpecifier = './message.js';
  const messageModule = await import(moduleSpecifier);
  messageModule.default(); // Hello, default export
  messageModule.sayGoodBye(); //Bye, named export
})();
</script>

And imported modules appear with default and named exports

export default () => {
    
    
  return "Hello, default export";
}
export const sayGoodBye = () => {
    
    
  return "Bye, named export"
}

Note: Dynamic import does not require script type="module"

3. Invalid coalescing operator

The void coalescing operator (??) is a logical operator that returns undefined for its right operand if its left operand is nullor, otherwise returns its left operand.
For the traditional || or operator, this operator replaces the operator to provide a default value if you consider null or '', 0, and NaN to be valid values. This is because the logical OR(||) operator treats (null or '', 0 and NaN) as false and returns the correct operand value, which is false in this case. So this operator is really checking for null value not false value.

let vehicle = {
    
    
  car: {
    
    
    name: "",
    speed: 0
  }
};

console.log(vehicle.car.name || "Unknown"); // Unknown
console.log(vehicle.car.speed || 90); // 90

console.log(vehicle.car.name ?? "Unknown"); // ""(empty is valid case for name)
console.log(vehicle.car.speed ?? 90); // 0(zero is valid case for speed)

In short, the null operator returns a non-null value and the || operator returns a true value.

4. Full string match

There is a String#match method that gets all matches of a string with a regular expression by iterating over each match. However, this method will give you the matched substring.

The String#matchAll() is a new method added to the String prototype that returns an iterator over all results where the string matches the regular expression.

const regex = /t(e)(st(\d?))/g;
const string = 'test1test2';
const matchesIterator = string.matchAll(regex);
Array.from(matchesIterator, result => console.log(result));

When you write this in the browser console, the match iterator produces an array for each match, including capturing groups with some extras.

["test1", "e", "st1", "1", index: 0, input: "test1test2", groups: undefined]
["test2", "e", "st2", "2", index: 5, input: "test1test2", groups: undefined]

5. Optional Links

In JavaScript, long chains of property accesses are error-prone if any of them evaluate to a null or undefined value. Also, it's not a good idea to check for the existence of a property on each item, which in turn leads to deeply nested structured if statements.
Optional chaining is a new feature that makes your JavaScript code look cleaner and more robust by appending the (?.) operator to stop evaluation and return undefined if the item is undefined or null.

let vehicle = {
    
    
};

let vehicle1 = {
    
    
  car: {
    
    
    name: 'ABC',
    speed: 90
  }
};

console.log(vehicle.car.name); // TypeError: Cannot read property 'name' of undefined

console.log(vehicle.car?.name); // Undefined
console.log(vehicle.car?.speed); // Undefined

console.log(vehicle1.car?.name); // ABC
console.log(vehicle1.car?.speed); // 90

console.log(vehicle.car?.name ?? "Unknown"); // Unknown
console.log(vehicle.car?.speed ?? 90); // 90

6. allSettled

Let me tell you that promise.all also receives an array list, but if any one fails, the execution will be interrupted, and the return value cannot be obtained for the success (unless the internal task of promise.all handles errors).
So allSettled is optimized for the problem of promise.all, directly returns the object and informs you of the execution result, and can also do error handling for the promise task.

const promise1 = new Promise((resolve, reject) => setTimeout(() => resolve(100), 1000));

const promise2 = new Promise((resolve, reject) => setTimeout(reject, 1000));

Promise.allSettled([promise1, promise2]).then(data => console.log(data)); // [
                                                                          // Object { status: "fulfilled", value: 100},
                                                                          // Object { status: "rejected", reason: undefined}
                                                                          // ]

7. globalThis

Before ES2020, you need to write different syntax in different JavaScript environments (cross-platform) to access the global object. window, self, or frames This is really a tough time for developers, because you need to use on browser side, globalnodejs side, selfweb workers side.

On the other hand, this keyword can be used inside functions in non-strict mode, but it gives undefined in strict mode. If you consider its Function('return this')() as a solution for the environment above, it will fail for environments with CSP enabled (eval() disabled).

In older versions, you can use es6-shim like this,

var 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');
};

var globals = getGlobal();

if (typeof globals.setTimeout !== 'function') {
    
    
  console.log('no setTimeout in this environment or runtime');
}

In ES2020, the globalThis property was introduced to provide a standard way to access the global this value across environments.

if (typeof globalThis.setTimeout !== 'function') {
    
    
  console.log('no setTimeout in this environment or runtime');
}

8. import.meta

9. for…in order

Prior to ES2020, the spec did not specify the order in which (a in b) was run. While most javascript engines/browsers iterate through an object's properties in the order they are defined, this is not the case for all. This has been officially standardized in ES2020.

var object = {
    
    
  'a': 2,
  'b': 3,
  'c': 4
}


for(let key in object) {
    
    
  console.log(key); // a b c
}

ES10

June 2019

1. Array flat and flatMap

Before ES2019, you need to use reduce() or concat() method to get flat array.

function flatten(arr) {
    
    
  const flat = [].concat(...arr);
  return flat.some(Array.isArray) ? flatten(flat) : flat;
}
flatten([ [1, 2, 3], ['one', 'two', 'three', [22, 33] ], ['a', 'b', 'c'] ]);

In ES2019, flat() was introduced to "flatten" nested arrays into top-level arrays. The function of this method is similar to Lodash's _.flattenDepth() function. This method accepts an optional parameter that specifies the number of levels by which the nested array should be flattened, the default nesting level is 1. NOTE: If there are any empty slots in the array, they will be discarded.

 const numberArray = [[1, 2], [[3], 4], [5, 6]];
 const charArray = ['a', , 'b', , , ['c', 'd'], 'e'];
 const flattenedArrOneLevel = numberArray.flat(1);
 const flattenedArrTwoLevel = numberArray.flat(2);
 const flattenedCharArrOneLevel = charArray.flat(1);

 console.log(flattenedArrOneLevel); // [1, 2, [3], 4, 5, 6]
 console.log(flattenedArrTwoLevel); // [1, 2, 3, 4, 5, 6]
 console.log(flattenedCharArrOneLevel); // ['a', 'b', 'c', 'd', 'e']

The flatMap() method combines map() and flat() into one method. It first creates a new array using the return value of the given function, and then concatenates all subarray elements of that array.

const numberArray1 = [[1], [2], [3], [4], [5]];

console.log(numberArray1.flatMap(value => [value * 10])); // [10, 20, 30, 40, 50]

2. Object.fromEntries()

Converting data from one format to another is very common in JavaScript. ES2017 introduced the Object.entries() method to put objects into an array.
Object to array:

     const obj = {
    
    'a': '1', 'b': '2', 'c': '3' };
     const arr = Object.entries(obj);
     console.log(arr); // [ ['a', '1'], ['b', '2'], ['c', '3'] ]

But if you want to get back object from array then you need to iterate and transform it like below

const arr = [ ['a', '1'], ['b', '2'], ['c', '3'] ];
let obj = {
    
    }
for (let [key, val] of arr) {
    
    
    obj[key] = val;
}
console.log(obj);

We need a straightforward way to avoid this iteration. In ES2019, Object.fromEntries() was introduced to perform the opposite behavior of Object.entries() . The loop above can be easily avoided as follows
for an iterable (such as an array or map) to an object

 const arr = [ ['a', '1'], ['b', '2'], ['c', '3'] ];
 const obj = Object.fromEntries(arr);
 console.log(obj); // { a: "1", b: "2", c: "3" }

A common case for using this method is with URL's query parameters

 const paramsString = 'param1=foo&param2=baz';
 const searchParams = new URLSearchParams(paramsString);

 Object.fromEntries(searchParams);    // => {param1: "foo", param2: "baz"}

3. trimStart and trimEnd

 //Prior ES2019
 let messageOne = "   Hello World!!    ";
 console.log(messageOne.trimLeft()); //Hello World!!
 console.log(messageOne.trimRight()); //   Hello World!!

 //With ES2019
 let messageTwo = "   Hello World!!    ";
 console.log(messageTwo.trimStart()); //Hello World!!
 console.log(messageTwo.trimEnd()); //   Hello World!!

4. Symbol description

When creating a symbol, you can also add a description to it for debugging purposes. But prior to ES2019 there was no way to directly access descriptions. With this in mind, ES2019 introduces a read-only description property to retrieve a string containing the symbol's description.

This makes it possible to access symbolic descriptions of different variants of symbolic objects

console.log(Symbol('one').description); // one

console.log(Symbol.for('one').description); // "one"

console.log(Symbol('').description); // ''

console.log(Symbol().description); // unefined

console.log(Symbol.iterator.description); // "Symbol.iterator"

5. Optional Capture Bindings

Before ES9, if you didn't need the error variable and omitted the same, the catch() clause would not be called. Also, linters complain about unused variables. To avoid this problem, the optional catch binding feature was introduced, making binding parameters in catch clauses optional. This is useful if you want to ignore the error completely, or if you already know about the error but you just want to react to it.

Let's see the syntax differences between the following versions

 // With binding parameter(<ES9)
 try {
    
    
   ···
 } catch (error) {
    
    
   ···
 }
 // Without binding parameter(ES9)
 try {
    
    
   ···
 } catch {
    
    
   ···
 }

6. JSON improvements

7. Stable array sorting

8. function.toString()

Functions have an instance method called toString(), which returns a string representing the function code. Previous versions of ECMAScript removed whitespace, newlines, and comments from function code, but it preserves the original source code in ES2020.

9. Private class variables

In ES6, classes were introduced to create reusable modules, and variables were declared in closures to make them private. Whereas in ES2020, private class variables were introduced to allow using variables only in classes. By prefixing our variables or functions with a simple hash notation, you can keep them completely inside the class.

 class User {
    
    
   #message = "Welcome to ES2020"

   login() {
    
     console.log(this.#message) }
 }

 const user = new User()

 user.login() // Welcome to ES2020
 console.log(user.#message) // Uncaught SyntaxError: Private field '#

ES9

Published June 2018

1. Asynchronous iteration object

Newly added for traversing asynchronous iterable objects, for-await-of
Look at ordinary forof, for asynchronous tasks, all are executed directly at one time, and the purpose of serialization cannot be achieved.

function getPromise(time) {
    
     
  return new Promise((resolve, reject) => {
    
    
    setTimeout(() => {
    
    
        resolve(time) 
     }, time) 
    })
}
let arr=[getPromise(100),getPromise(200),getPromise(300)]

for(const i of arr){
    
    
    console.log(i)
}
// Promise{<pending>}
// Promise{<pending>}
// Promise{<pending>}

Asynchronous for-await-of can be done serially.

function getPromise(time) {
    
     
  return new Promise((resolve, reject) => {
    
    
    setTimeout(() => {
    
    
        resolve(time) 
     }, time) 
    })
}
let arr=[getPromise(100),getPromise(200),getPromise(300)]

for await (const i of arr){
    
    
    console.log(i)
}
//100
//200
//300

2. Object extension

ES6 supports array extensions, such as the following code

 function myfunc(p1, p2, ...p3) {
    
    
   console.log(p1, p2, p3); // 1, 2, [3, 4, 5, 6]
 }
myfunc(1, 2, 3, 4, 5, 6);
 const myArray = [10, 5, 25, -100, 200, -200];
 console.log( Math.max(...myArray) ); // 200

Now es9 supports object extender

 function myfunc1({
    
     a, ...x }) {
    
    
   console.log(a, x); // 1, { b: 2, c: 3, d:4 }
 }
 myfunc1({
    
    
   a: 1,
   b: 2,
   c: 3,
   d: 4
 });
const myObject = {
    
     a: 1, b: 2, c: 3, d:4 };
const myNewObject = {
    
     ...myObject, e: 5 }; // { a: 1, b: 2, c: 3, d: 4, e: 5 }

3. Promise finally

Sometimes you may need to avoid duplication of code in then() and catch() methods.

myPromise
   .then(result => {
    
    
     // process the result and then clean up the resources
   })
   .catch(error => {
    
    
     // handle the error and then clean up the resources
   });

This method is useful if you want to do some processing or resource cleanup after the promise is resolved (i.e. fulfilled or rejected).

  let isLoading = true;
  fetch('http://somesite.com/users')
     .then(data => data.json())
     .catch(err => console.error(err))
     .finally(() => {
    
    
       isLoading = false;
       console.log('Finished loading!!');
     })

ES8

Published June 2017

1. Async functions

In order to solve the problem of callback hell, es6 adds a promise function to solve it, but promise brings a new problem, that is, the chain is too long, making it difficult to maintain.

new Promise((resolve, reject) => {
    
    this.login(resolve)})
.then(() => this.getInfo())
.then(() => {
    
    // do something})
.catch(() => {
    
     console.log("Error") })

So the Generator function was born, which allows on-demand execution of tasks, manages and executes tasks through yield and next, but the process is still not clear enough

const gen = function* () {
    
    
const f1 = yield this.login()
const f2 = yield this.getInfo()
};

Now, es8 provides async/await to complete asynchronous tasks with its minimalist syntax

async function logger() {
    
    
  let data = await fetch('http://someapi.com/users'); // pause until fetch returns
    console.log(data)
}
logger();

2. Object.values()

Similar to Object.keys which iterates over the keys of a JavaScript object, Object.values ​​will do the same for the values. Namely, the Object.values() method was introduced to return an array of enumerable property values ​​for a given object itself, in the same order as the loop for…in

 const countries = {
    
    
   IN: 'India',
   SG: 'Singapore',
 }
 Object.values(countries) // ['India', 'Singapore']

Non-object arguments will be coerced to objects

console.log(Object.values(['India', 'Singapore'])); // ['India', 'Singapore']
console.log(Object.values('India')); // ['I', 'n', 'd', 'i', 'a']

3. Object.entries()

The Object.entries() method is introduced to return an array of enumerable string-keyed property [key, value] pairs for a given object itself, in the same order as a for…in loop.

   const countries = {
    
    
     IN: 'India',
     SG: 'Singapore',
   }
   Object.entries(countries) // [["IN", "India"], ["SG", "Singapore"]]

Non-object arguments will be coerced to objects

   const countriesArr = ['India', 'Singapore'];
   console.log(Object.entries(countriesArr)); // [ ['0', 'India'], ['1', 'Singapore']]

   const country = 'India';
   console.log(Object.entries(country)); // [["0", "I"], ["1", "n"], ["2", "d"], ["3", "i"], ["4", "a"]]

   console.log(Object.entries(100)); // [], an empty array for any primitive type because it won't have any own properties

4. Object property descriptors

5. String padding

Some strings and numbers (money, dates, timers, etc.) need to be represented in a specific format. Both padStart() & padEnd() methods introduced pad a string with another string until the resulting string reaches the provided length.

padStart(): With this method, padding is applied to the left or beginning of the string.
For example, you may only want to display the last four digits of a credit card number for security reasons

const cardNumber = '01234567891234';
const lastFourDigits = cardNumber.slice(-4);
const maskedCardNumber = lastFourDigits.padStart(cardNumber.length, '*');
console.log(maskedCardNumber); // expected output: "**********1234"

padEnd(): Using this method, padding is applied to the right or end of the string.
For example, the configuration file information populated for labels and values ​​is as follows

const label1 = "Name";
const label2 = "Phone Number";
const value1 = "John"
const value2 = "(222)-333-3456";

console.log((label1 + ': ').padEnd(20, ' ') + value1); // Name:                     John
console.log(label2 + ": " + value2); // Phone Number: (222)-333-3456

ES7

Published June 2016

1. includes

Before ES7, you had to use the indexOf method to compare the result to '-1' to check if an array element contained a specific element.

 const array = [1,2,3,4,5,6];
 if(array.indexOf(5) > -1 ){
    
    
   console.log("Found an element");
 }

Whereas in ES7, the array.prototype.includes() method was introduced as a direct way to determine whether an array contains a certain value in its entries.

const array = [1,2,3,4,5,6];
if(array.includes(5)){
    
    
  console.log("Found an element");
}

Besides that, Array.prototype.includes() handles NaN and Undefined values ​​better than Array.prototype.indexOf() method. That is, if the array contains NaN and Undefined values, indexOf() will not return the correct index when searching for NaN and Undefined.

let numbers = [1, 2, 3, 4, NaN, ,];
console.log(numbers.indexOf(NaN)); // -1
console.log(numbers.indexOf(undefined)); // -1

On the other hand, the includes method is able to find these elements

let numbers = [1, 2, 3, 4, NaN, ,];
console.log(numbers.includes(NaN)); // true
console.log(numbers.includes(undefined)); // true

2. Exponential operator

Older versions of javascript used the Math.pow function to find the power of a given number. ECMAScript 2016 introduced the exponentiation operator** (similar to other languages ​​such as Python or F#), which computes exponentiations in a clear representation using infix notation.

//Prior ES7
const cube = x => Math.pow(x, 3);
console.log(cube(3)); // 27

//Using ES7
const cube1 = x => x ** 3;
console.log(cube1(3)); // 27

ES6

Published June 2015

Because of serious differences within the tc39 early team, es6 could not be released until nearly ten years later.

1. Variable scope

Variable scope determines the visibility or accessibility of a variable within a specific part of a program or region.
In ES6, both the const and let keywords allow developers to declare variables at block scope.
The let statement declares a block-scope local variable that can be reassigned. That is, a let declaration creates a mutable variable.

let a = 1;

if (a === 1) {
    
    
  let a = 2;

  console.log(a); //2
}

console.log(a); //1

const variables are similar to let variables, but they cannot be changed by reassignment. That is, a const declaration creates a read-only reference to a value.

const x = 1;

if (x === 1) {
    
    
    const y = 2; // You cannot re-assign the value similar to let variable

    console.log(y); //2
}

console.log(x); //1

The difference between const and let and var

const

The variable defined by var can be pre-parsed, and the result of the early call is undefined. The variable defined by const cannot be pre-parsed, and the result of the early call is an error.
For variables defined by var, the variable name can be repeated, and the effect is repeated assignment. Variables defined by const cannot be repeated, otherwise the execution will report an error.
The variable scope defined by var is global/local scope. If a variable defined by const is in {}, it can only be called in {}.
The data value stored in the variable defined by const cannot be changed, that is, the variable defined by const cannot be assigned repeatedly.

let

Variables defined by var can be pre-parsed, and the result of calling ahead is undefined. Variables defined by let cannot be pre-parsed, and the result of calling ahead is an error.
For variables defined by var, the variable name can be repeated, and the effect is repeated assignment. Variables defined by let cannot be repeated, otherwise the execution will report an error.
The variable scope defined by var is global/local scope. If the variable defined by let is in {}, it can only be called in {}.
The loop variable defined by var and the loop variable defined by let in the loop statement. The principle of execution and the effect of execution are different.

2. Arrow functions

Arrow function advanced feature description
Arrow functions provide a more concise syntax for writing function expressions by using the thick arrow (=>) notation to opt out of a function and the return keyword. Let's see what this arrow function looks like

// Function Expression
var multiplyFunc = function(a, b) {
    
    
  return a * b;
}
console.log(multiplyFunc(2, 5)); // 10

// Arrow function
var multiplyArrowFunc = (a, b) => a * b;
console.log(multiplyArrowFunc(2, 5)); // 10

You can also skip the parentheses (()) if the function has only one parameter (zero or more parameters). Additionally, if there are multiple expressions within a function body, you can enclose them in curly braces ({}).

Let's list all variants of arrow functions

//1. Single parameter and single statement
const message = name => console.log("Hello, " + name + "!");
message("Sudheer"); // Hello, Sudheer!

//2. Multiple parameters and single statement
const multiply = (x, y) => x * y;
console.log(multiply(2, 5)); // 10

//3. Single parameter and multiple statements
const even = number => {
    
    
  if(number%2) {
    
    
    console.log("Even");
  } else {
    
    
    console.log("Odd");
  }
}
even(5); // odd

//4. Multiple parameters and multiple statements
const divide = (x, y) => {
    
    
  if(y != 0) {
    
    
    return x / y;
  }
}
console.log(divide(100, 5)); // 20

//5. No parameter and single statement
const greet = () => console.log('Hello World!');
greet(); // Hello World!

3. class

These classes are introduced as syntactic sugar for the existing prototype-based inheritance and constructors. So this feature doesn't bring a new object-oriented inheritance model to JavaScript.

There are two ways to define a class

class declaration
class Square {
    
    
  constructor(length) {
    
    
    this.length = length;
  }

  get area() {
    
    
    return this.length * this.length;
  }

  set area(value) {
    
    
    this.area = value;
  }
}
class expression

const square = class Square {
constructor(length) {
this.length = length;
}

get area() {
return this.length * this.length;
}

set area(value) { this.area = value; } } You can use the extend keyword to use inheritance. This enables subclasses to get all the functionality of the parent class.



class Vehicle {
    
    
  constructor(name) {
    
    
    this.name = name;
  }

  start() {
    
    
    console.log(`${
      
      this.name} vehicle started`);
  }
}

class Car extends Vehicle {
    
    
  start() {
    
    
    console.log(`${
      
      this.name} car started`);
  }
}

const car = new Car('BMW');
console.log(car.start()); // BMW car started

4. Enhanced Object Literals

Object literals are extended to support setting the prototype at construction time, shorthand for foo:foo assignment, defining methods, making hypercalls, and evaluating property names with expressions.

attribute shorthand

Properties of objects are usually created from variables with the same name.
Let's look at the ES5 representation.

var a = 1, b = 2, c = 3,
  obj = {
    
    
    a: a,
    b: b,
    c: c
  };
  console.log(obj);

It can be expressed in a shorter syntax as follows

const a = 1, b = 2, c = 3;
const obj = {
    
    
  a,
  b,
  c
};
console.log(obj);
method shorthand

In ES5, object methods require function statements like

var calculation = {
    
    
  sum: function(a, b) {
    
     return a + b; },
  multiply: function(a, b) {
    
     return a * b; }
};

console.log(calculation.sum(5, 3));  // 8
console.log(calculation.multiply(5, 3)); // 15

This can be avoided in ES6

const calculation = {
    
    
  sum(a, b) {
    
     return a + b; },
  multiply(a, b) {
    
     return a * b; }
};

console.log(calculation.sum(5, 3));  // 8
console.log(calculation.multiply(5, 3)); // 15

In ES5, it is not possible to use variables as keys during object creation.

var
  key = 'three',
  obj = {
    
    
    one: 1,
    two: 2
  };

obj[key] = 3;

In ES6, object keys can be assigned dynamically by enclosing expressions in square brackets ([])

const
  key = 'three',
  computedObj = {
    
    
    one: 1,
    two: 2,
    [key]: 3
  };

5. Template strings

Before ES6, JavaScript developers needed to do ugly string concatenation to create dynamic strings.
Template literals allow you to handle strings in a new way compared to ES5. These are just string literals that allow embedding expressions denoted by dollar signs and braces (${expression}). Also, these literals are enclosed by backtick ( `) characters rather than double or single quotes.

template literal

String literals that exist across multiple lines, including interpolated expressions (i.e. ${expression}).

const firstName = 'John';
console.log(`Hello ${
      
      firstName}!
Good morning!`);
tagged template text

A function call created by mentioning the function before the template literal.

const Button = styled.a`
  display: inline-block;
  border-radius: 3px;
`

6. Destructuring assignment

Destructuring is a javascript expression used to extract multiple values ​​from data stored in objects (properties of objects) and arrays.

object deconstruction

This function is used to extract a value from an object.

const user = {
    
     firstName: 'John', lastName: 'Kary' };
const {
    
    firstName, lastName} = user;
console.log(firstName, lastName); // John, Kary
array destructuring

This function is used to extract values ​​from an array.

const [one, two, three] = ['one', 'two', 'three'];
console.log(one, two, three); // one, two, three

Can also be applied in the following places

  1. variable declaration
  2. object allocation
  3. parameter definition
  4. for loop

7. Parameter default values

Default parameters allow a named parameter of a function to be initialized with a default value if no value is passed or is undefined.
Before ES6, you needed to check for undefined values ​​and provide default values ​​for undefined values ​​using if/else or the ternary operator.

function add(a, b) {
    
    
  a = (typeof a !== 'undefined') ? a : 10;
  b = (typeof b !== 'undefined') ? b : 20;
  return a + b;
}
add(20); // 40
add(); // 30

In ES6, these checks can be avoided by using default parameters.

function add(a = 10, b = 20) {
    
    
  return a + b;
}
add(20); // 40
add(); // 30

8. Remaining parameters

The rest parameter is used to represent a variable number of parameters as an array. The point here is that only the last parameter of a function can be a "residual parameter". This feature was introduced to reduce boilerplate code caused by parameters.

function sum(...args) {
    
    
  return args.reduce((previous, current) => {
    
    
    return previous + current;
  });
}

console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4)); // 10
console.log(sum(1, 2, 3, 4, 5)); // 15

9. Array stretcher

In function and constructor calls, the spread operator converts iterable values ​​into arguments.

console.log(Math.max(...[-10, 30, 10, 20])); //30
console.log(Math.max(-10, ...[-50, 10], 30)); //30

In array literals and strings, the spread operator converts iterable values ​​into array elements.

console.log([1, ...[2,3], 4, ...[5, 6, 7]]); // 1, 2, 3, 4, 5, 6, 7

10. Array iterator and forof

String, Array, TypedArray, Map, and Set are all built-in iterable objects, but objects are not iterable by default. Iterators are a new way to loop over any collection in JavaScript. These objects define a sequence and may return a value when it terminates. Iterators implement the Iterator protocol by having a next() method that returns an object with two properties.

value: The next value in the iterated sequence.
done: Returns true if the last value in the sequence has been consumed.

You can make an object iterable by defining a Symbol.iterator property on it.

const collection = {
    
    
  one: 1,
  two: 2,
  three: 3,
  [Symbol.iterator]() {
    
    
    const values = Object.keys(this);
    let i = 0;
    return {
    
    
      next: () => {
    
    
        return {
    
    
          value: this[values[i++]],
          done: i > values.length
        }
      }
    };
  }
};

const iterator = collection[Symbol.iterator]();

console.log(iterator.next());    // → {value: 1, done: false}
console.log(iterator.next());    // → {value: 2, done: false}
console.log(iterator.next());    // → {value: 3, done: false}
console.log(iterator.next());    // → {value: undefined, done: true}

for (const value of collection) {
    
    
  console.log(value);
}

11. Generators

A generator is a function that can be stopped or paused in the middle and then continue from where it left off while maintaining the context (saved on re-entry). It can be defined using a function keyword followed by an asterisk (ie, function* ()).
This function returns an iterator object whose next() method returns an object with a value property containing the yielded value and a done property indicating whether the generator has yielded its last value.

function* myGenerator(i) {
    
    
  yield i + 10;
  yield i + 20;
  return i + 30;
}

const myGenObj = myGenerator(10);

console.log(myGenObj.next().value); // 20
console.log(myGenObj.next().value); // 30
console.log(myGenObj.next().value); // 40

12. module

heavyweight features
Modules are small, self-contained, reusable units of code that serve as building blocks in Javascript applications.
Prior to ES6, there was no native module support in JavaScript. Three main module standards are used.

  1. Asynchronous Module Definition (AMD)
  2. RequireJS modules
  3. CommonJS modules (module.exports and require syntax used in Node.js)

ES6 provides built-in support for modules. By default, everything inside a module is private and operates in strict mode. Public variables, functions, and classes are all exposed with a usingexport statement and imported with the same usingimport statement.

What is the difference from the past commonjs specification?

  1. Module is loaded at compile time, that is, statically loaded, and the dependencies of the module, as well as input and output variables can be determined at compile time; commonjs is loaded at runtime, and these things can only be determined at runtime when the code is running.
  2. The module can do tree-shaking, that is, it can load the content used in the module part, while commonjs needs to load the entire module, and then fetch the content.
  3. The output of module is a reference to the value, and the output of commonjs is a copy of the value.
  4. The import in the module is loaded asynchronously, and the require in commonjs is loaded synchronously
export statement
// module "my-module.js"

const PI = Math.PI;

function add(...args) {
    
    
  return args.reduce((num, tot) => tot + num);
}

function multiply(...args) {
    
    
  return args.reduce((num, tot) => tot * num);
}

// private function
function print(msg) {
    
    
  console.log(msg);
}

export {
    
     PI, add, multiply };
// module "my-module.js"

export default function add(...args) {
    
    
  return args.reduce((num, tot) => tot + num);
}
import statement
// 1. Import an entire module's contents
import * as name from "my-module";

//2.Import a single export from a module
import {
    
     export1 } from "my-module";

//3.Import multiple exports from a module
import {
    
     export1 , export2 } from "my-module";

//4.Import default export from a module
import defaultExport from "my-module";

//5.Import an export with an alias
import {
    
     export1 as alias1 } from "my-module";

13 set

Set is a built-in object used to store a collection of unique values ​​of any type.

let mySet = new Set()

mySet.add(1);
mySet.add(2);
mySet.add(2);
mySet.add('some text here');
mySet.add({
    
    one: 1, two: 2 , three: 3});
console.log(mySet); // Set [ 1, 2, 'some text here', {one: 1, two: 2 , three: 3} ]
console.log(mySet.size) // 4
console.log(mySet.has(2)); // true

14. map

A Map is a collection of elements, where each element is stored as a key-value pair. It can hold objects and primitive values ​​as keys or values, and iterate over its elements in insertion order.

let typeMap = new Map();

var keyObj = {
    
    'one': 1}

typeMap.set('10', 'string');   // a string key
typeMap.set(10, 'number');     // a numeric key
typeMap.set(true, 'boolean');  // a boolean key
typeMap.set(keyObj, 'object'); // an object key


console.log(typeMap.get(10));         // number
console.log(typeMap.get('10'));       // string
console.log(typeMap.get(keyObj));     // object
console.log(typeMap.get({
    
    'one': 1})); // undefined

console.log(typeMap.size ); // 3

for(let item of typeMap) {
    
    
  console.log(item);
}


for(let item in typeMap) {
    
    
  console.log(item);
}

15. Symbol

16. promise

A Promise is an object that represents the eventual completion or failure of an asynchronous operation.

It is in one of the following states:

pending: Represents the initial state, neither completed nor rejected. fulfilled: Indicates that the operation completed successfully. rejected: Indicates that the operation failed.

A promise is said to be resolved if it is either fulfilled or rejected, but not pending. The instance methods promise.then() , promise.catch() , and promise.finally() are used to associate further actions with the committed promise. These methods also return a newly generated promise object, which can optionally be used for chaining.
insert image description here

const promise = new Promise(function(resolve, reject) {
    
    
  setTimeout(() => resolve(1), 1000);
});

promise.then(function(result) {
    
    
    console.log(result); // 1

    return result * 2;
  }).then(function(result) {
    
    
    console.log(result); // 2

    return result * 3;
  }).then(function(result) {
    
    
    console.log(result); // 6

    return result * 4;
  }).catch(function(error){
    
    
    console.log(error);
  });

17. Array methods

S6 introduced some array methods, two of which are Array.find() and Array.findIndex().

ES5

w3schools
Released mid-2009

1. “use strict”

2. String[number] access

3. Multiline strings

4. String.trim()

5. Array.isArray()

6. Array forEach()

7. Array map()

8. Array filter()

9. Array reduce()

10. Array reduceRight()

11. Array every()

12. Array some()

13. Array indexOf()

14. Array lastIndexOf()

15. JSON.parse()

16. JSON.stringify()

17. Date.now()

18. Date toISOString()

19. Date toJSON()

20. Property getters and setters

21. Reserved words as property names

22. Object methods

23. Object defineProperty()

24. Function bind()

25. Trailing commas

Guess you like

Origin blog.csdn.net/qq_42427109/article/details/130564336
Recommended