ES6 New Features Introduction

1. The relationship between ES6 and JavaScript

        JavaScript was invented by Brendan Eich in 1995 and became an ECMA standard in 1997.

        ECMAScript is the official name of the language.

        From 2015, ECMAScript is named by year (ECMAScript 2015).

        ES6 refers to the sixth-generation version of ECMAScript, which is also called ECMAScript 2015 because it was released in 2015.

        ECMAScript major version:

        Browser support:

 

2. Variable declaration const and let

   ES6 adds the const keyword for declaring constants, and the let keyword for declaring variables.

        The variable declared by const is a constant, and the constant must be assigned a value when it is declared, and cannot be modified after declaration:

const PI = 3.14;
PI = 3.1415;  //报错 Uncaught TypeError: Assignment to constant variable.

        If the constant declared by const is an object, the attribute value contained in the object can be modified, but it cannot be replaced with a new object, that is, the reference address of the object cannot be modified:

const car = {color:'red'};
car.color = 'black';     //可以修改  111027110181937
car = {color:'black'};   //报错 Uncaught TypeError: Assignment to constant variable.

        const is block-level scope, that is, it is valid within the scope of the curly braces it belongs to. Out of range program will throw error:

{
    var i = 1;
 	 const j = 2;
}
console.log("i=" + i);   //输出 i=1
console.log("j=" + j);   //报错 Uncaught ReferenceError: j is not defined

        Like const, variables declared by let are also block-level scoped, that is, they are valid within the scope of the curly braces they belong to. Out of range program will throw error:

{
    var i = 1;
 	 let j = 2;
}
console.log("i=" + i);   //输出 i=1
console.log("j=" + j);   //报错 Uncaught ReferenceError: j is not defined

        Different from var, the variable declared by the let keyword does not have the variable hoisting feature:

console.log("i=" + i);  //输出 i=undefined
var i = 1;
console.log("j=" + j);  //报错 VM320:3 Uncaught ReferenceError: j is not defined
let j = 2;

        Different from var, let variables cannot be declared repeatedly in the same scope:

var i = 1;
var i = 2;   //可以重复声明
let j = 3;
let j = 4;   //报错 VM287:4 Uncaught SyntaxError: Identifier 'j' has already been declared

        The variable hoisting feature of var:

var i = 1;             // 全局变量i
f();                   // f是函数,虽然定义在调用的后面,但是函数声明会提升到作用域的顶部。 
console.log(i);        // i = 1,  当前为全局变量i
function f() {
  console.log(i);      // 当前i是下一行的i的声明提升后的默认值undefined
  var i = 2;           //局部变量
  console.log(i);      // i = 2
}

        operation result:

        The scope of let in a for loop:

for (var i = 0; i < 10; i++) {
   setTimeout(function () {
    console.log("i=" + i);
  }, 0);
}      // 输出 10次 i=10
for (let j = 0; j < 10; j++) {
   setTimeout(function () {
    console.log("j=" + j);
  }, 0);
}     // 循环输出 j=0 到 j=9

        operation result:

3. Template string

 The template string (template string) is an enhanced version of the traditional javascript string. Use backticks `` to identify. It can be used as a normal string, and can also be used to conveniently handle multi-line strings and embed variables in strings.

        Ordinary string. Consistent with traditional javascript string usage:

 let hello = `hello world`;

        If you need to use backticks in the string, you need to add a backslash in front of it to escape:

let hi = `\`hi\`, dude`;

        Handles multiline strings. It is a complicated and painful thing to use + or concat() to splice when traditional strings need to use newlines and indents. The template string allows arbitrary newlines and indentations within the backquote range, and all newline and indentation formats can be preserved, which is very convenient:

let table = `
        <table>
            <tr>
                <td>cell</td>
                <td>cell</td>
            </tr>
        </table>
        `;
console.log(table);

        Print result:

         Embed variables in strings. Traditional strings can be concatenated using + to embed variables into strings, and template strings use ${ } to embed variables into strings:

let job = "程序员", salary = "100";

//传统字符串拼接拼接
let say = "我的工作是" + job + ", 我每月可以挣" + salary + "大洋,真开心!";  

//模板字符串嵌入
say = `我的工作是${job}, 我每月可以挣${job}大洋,真开心!`;                   

        ${ } can be placed directly into a string or into a variable, expression, object, or method. If the value in curly braces is not a string, it will be converted to a string according to the normal rules. For example, if there is an object in curly braces, the toString() method of the object will be called by default.

4. Destructuring assignment

        Destructuring assignment is an extension to the assignment operator. It is a pattern matching for arrays or objects, and then assigns values ​​to the variables in it.

        Array destructuring assignment:

let [a1, a2, a3] = [1, 2, 3];
console.log(`a1=${a1},a2=${a2},a3=${a3}`);
let [b1, , b2] = [1, 2, 3];
console.log(`b1=${b1},b2=${b2}`);
let [c1, c2, c3, c4, c5] = 'hello';
console.log(`c1=${c1},c2=${c2},c3=${c3},c4=${c4},c5=${c5}`);

        Output result:

        Object destructuring assignment:

let a1 = { x, y } = { x: 'aaa', y: 'bbb' };
console.log(a1);  //a1.x='aaa', a1.y='bbb'
let a2 = { x: ['hello', { z: 'world' }] };
let a3 = { x: [y, { z }] } = a2;
console.log(a3);  //a3.x[0]='hello', a3.x[1].z='world'

         Output result:

        Destructuring the default value, when the property of the destructured object has no value or even does not exist, the default value can be set:

let [x = 1, y = 2, z = 3] = [4, undefined, 6];
console.log(`x=${x},y=${y},z=${z}`);
function fun({ x = 1, y = 2, z }) {
    console.log(`x=${x},y=${y},z=${z}`);
}
fun({});
fun({ x: 3 });
fun({ x: 4, z: 5 });
fun({ x: 6, y: 7, z: 8 });
fun({ z: 9 });

         Output result:

 5. Spread operator

        The spread operator is three dots... , which converts an array into a sequence of arguments:

function add(x, y) {
    return x + y;
}
let numbers = [1, 2];
console.log(add(...numbers));

        Output result:

        Combined with an array destructuring expression, ... can also be called the remainder operator:

let [a, b, ...c] = [1, 2, 3, 4, 5, 6];
console.log(a, b, c);

         Output result:

        That is...c matches the remaining part of the array after removing the previously determined variables a and b.

        Note: The rest operator can only be placed before the last variable when combined with the destructuring expression, and an exception will be thrown before the previous variable:

 let [...a, b, c] = [1, 2, 3, 4, 5, 6]; 
//报错 Uncaught SyntaxError: Rest element must be last element
 let [x, ...y, z] = [1, 2, 3, 4, 5, 6]; 
//报错 Uncaught SyntaxError: Rest element must be last element

        Combined with object destructuring expressions:

let { a, b, ...rest } = { a: 1, b: 2, c: 3, d: 4 };
console.log(a, b, rest);

        Output result:

         Also the rest operator throws an exception when placed before the previous variable:

let { ...rest, a, b } = { a: 1, b: 2, c: 3, d: 4 }; 
//报错 Uncaught SyntaxError: Rest element must be last element

        For array splicing, use the ... operator to perform array splicing operations:

 let a = [1, 2], b = [4, 5];
 let c = [...a, ...b];
 let d = 3;
 //单个元素加入拼接,对应变量无需使用 ... 运算符
 let e = [...a, d, ...b];
 console.log(c,e);

        Output result:

         Object copy assignment. Use the ... operator to copy the source object to the target object. After copying, you need to pay attention to the scope of field value modification:

let src = { user: 'admin', password: '123456', job: { title: 'lawyer', salary: 1000 } };
let tar = { ...src, tel: '110' };
src.password = '888888';      //源单独修改
tar.user = 'user';            //目标单独修改
src.job.title = 'teacher';    //源和目标同步修改
tar.job.salary = 200;         //源和目标同步修改
console.log(src, tar);

        Output result:

        It can be seen that the source and target of non-object attribute modification are independent and independent of each other; the source and target of object attribute modification change synchronously, because the index address of the object has not changed. 

let tar = {...src };  //可以当做是src的浅拷贝

        This method of copy assignment has the same effect as Object.assign():

let src = { user: 'admin', password: '123456', job: { title: 'lawyer', salary: 1000 } }, tar={ tel: '110' };
Object.assign(tar, src);
src.password = '888888';
tar.user = 'user';
src.job.title = 'teacher';
tar.job.salary = 200;
console.log(src, tar);

        Output result:

 6. Arrow functions

        Before ES6, use a normal function to convert each string in an array to uppercase:

const upperCaseStr = ['Hello', 'World'].map(function (src) {
    return src.toUpperCase();
});

        Use arrow functions:

const upperCase = ['Hello', 'World'].map(str => str.toUpperCase());

        By comparison, it can be found that the code writing has been greatly simplified. There is only one parameter of the function, and there is no need to use () to wrap it, but if there is more than one parameter, the parameter list must be placed in parentheses:

const add = (a, b) => a + b;

        Generally, an arrow function has only one expression as the function body, so there are no curly braces {} and the expression is automatically returned. If multiple lines of code are required inside the arrow function, you need to use regular syntax. According to the conventional syntax, the above arrow function can be written in the following format:

const upperCaseStr = ['Hello', 'World'].map(str => {
    return str.toUpperCase();
});
const add = (a, b) => {
    return a + b;
};

        The effect of arrow functions on this: For ordinary functions, the value of this is based on how the function is called:

function Counter() {
    this.count = 0;
}
Counter.prototype.addCount = function () {
   setTimeout(function () {
        this.count++;
        console.log(`count: ${this.count}`);
    }, 100);
}

const counter = new Counter();
counter.addCount();             //输出 count: NaN

        The function passed to setTimeout() is invoked without new, call(), or apply(), nor with the context object. It means that the value of this inside the function is the global object, not the counter object. What actually happens is that inside the function called by setTimeout a new count variable is created (default value is undefined) and then incremented (undefined + 1 results in NaN).

        For arrow functions, the value of this is based on the context surrounding the function, and the value of this is the same as the value of this outside the function:

function Counter() {
    this.count = 0;
}
Counter.prototype.addCount = function () {
    setTimeout(() => {
        this.count++;
        console.log(`count: ${this.count}`);
    }, 100);
}
const counter = new Counter();
counter.addCount();             //输出 count: 1

        The value of this in the above arrow function is the same as the external this value, both pointing to the counter object of the call.

7、Promise

        Promise is a solution for asynchronous programming in ES6. Compared with the traditional callback function and event solution, Promise can express asynchronous operations in the process of synchronous operations, avoiding layers of nested callback functions.

        Promise has three states: Pending (in progress), Resolved (completed, also known as Fulfilled), and Rejected (failed). Let's look at a simple usage example:

new Promise(
    function (resolve, reject) {
        let score = Math.round(Math.random() * 100);  //通常是耗时较长的异步操作。
        console.log(`score: ${score}`);
        if (score >= 60) {
            resolve('pass');
        } else {
            reject("fail");
        }
    }
).then(function resolveCallback(data) {
    console.log(`resolved data : ${data}`);
}, function rejectCallback(data) {
    console.log(`reject data : ${data}`);
});

        The result of the operation is as follows:

        The function function(resolve, reject){} when new Promise() is constructed is used to handle asynchronous operations. Set the Promise state by calling resolve() and reject() based on the result of the asynchronous operation. The first parameter in the then() method is the callback method for processing the Resolved state, and the second parameter is the callback method for processing the Rejected state.

        Promise allows only setting the Resolved state, and the corresponding then() method only needs a callback method to handle the Resolved state:

new Promise(
    (good) => {
        // 一些异步操作
        good('pass');
    }
).then((data) => {
    console.log(`resolved data : ${data}`);
});

         operation result:

        The state of Promise can only be set once, multiple settings will not take effect:

new Promise(
    (pass, fail) => {
        // 一些异步操作 
        pass('pass');  // 设置状态为 Resolved  成功设置
        fail('fail');  // 设置状态为 Rejected  不能成功设置
    }
).then((data) => {
    console.log(`resolved data : ${data}`);
}, (data) => {
    console.log(`reject data : ${data}`);
});

         operation result:

         Promise provides Promise.all and Promise.race methods to deal with multiple Promise problems.

        Promise.all combines multiple Promise instances into one instance, and only when all instances become Resolved will the callback be executed:

const p1 = new Promise((get) => {
    setTimeout(() => {
        console.log('大王');
        get("大王");
    }, 200);
});
const p2 = new Promise((get) => {
    setTimeout(() => {
        console.log('小王');
        get();
    }, 100);
});
Promise.all([p1, p2]).then(data => {
    console.log(data);
    console.log(' 王炸!');
});

        operation result:

        The data in then() is the Promise instance array [p1,p2] corresponding to the passed parameter array [data1,data2], data1 is 'King', p2 does not pass the parameter data2 is undefined.

        Promise.race also wraps multiple Promise instances into a new Promise instance. As long as one of the multiple instances changes state, the state of the instance changes. The state of the first changed instance is returned:

const pTimeout = new Promise((resolve) => {
    setTimeout(() => {
        console.log('pTimeout resolve');
        resolve({ code: 'TIMEOUT' });
    }, 100);
});
const pRequest = new Promise((resolve) => {
    setTimeout(() => {
        console.log('pRequest resolve');
        resolve({ code: 'OK', data: {} });
    }, 200);
});
Promise.race([p1, p2]).then(res => {
    if (res.code === 'OK') {
        console.log('request ok');
    } else {
        console.log('request timeout');
    }
});

         operation result:

         The above code simulates the interface data request processing request timeout situation, pTimeout sets the timeout time to 100 ms, pRequest simulates the data request and returns data after 200 ms, the state of the two asynchronous operations pTimeout changes first, the packaged Promise instance changes accordingly, and the print request times out, if pRequest A print request succeeds before pTimeout changes state.

8、async, await

        async and await are used to handle asynchrony. That is, you need to execute asynchronously like synchronously, and after returning the result asynchronously, continue execution based on the result.

        async is shorthand for "asynchronous", and await can be thought of as shorthand for async wait. async is used to declare that a function is asynchronous, and await is used to wait for an asynchronous method to complete.

        Compared with the traditional callback method and Promise writing method, async-await allows us to write code more smoothly, and also enhances the readability of the code.

        The traditional callback method handles multiple asynchronous processes:

    const getUp = function (callback) {
            setTimeout(() => {
                console.log('get up at 7:00.')
                callback();
            }, 100);
        }
        const washFace = function (callback) {
            setTimeout(() => {
                console.log('wash face at 7:10.')
                callback();
            }, 100);
        }
        const brushTeeth = function (callback) {
            setTimeout(() => {
                console.log('brush teeth at 7:20.')
                callback();
            }, 100);
        }
        const haveBreakfast = function (callback) {
            setTimeout(() => {
                console.log('have breakfast at 7:30.')
                callback();
            }, 100);
        }
        const goToWork = function () {
            setTimeout(() => {
                console.log('go to work at 8:00.')
            }, 100);
        }
        const happyDay = function () {
            getUp(function () {
                washFace(function () {
                    brushTeeth(function () {
                        haveBreakfast(function () {
                            goToWork();
                        });
                    });
                });
            });
        }
        happyDay();

        operation result:

 Promises handle multiple asynchronous processes:

const getUp = function () {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log('get up at 7:00.')
                    resolve();
                }, 100);
            });
        }
        const washFace = function () {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log('wash face at 7:10.')
                    resolve();
                }, 100);
            });
        }
        const brushTeeth = function () {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log('brush teeth at 7:20.')
                    resolve();
                }, 100);
            });
        }
        const haveBreakfast = function () {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log('have breakfast at 7:30.')
                    resolve();
                }, 100);
            });
        }
        const goToWork = function () {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log('go to work at 8:00.')
                    resolve();
                }, 100);
            });
        }
        const happyDay = function () {
            getUp().then(washFace()).then(brushTeeth()).then(haveBreakfast()).then(goToWork());
        }
        happyDay();

        operation result:

        Note: Because Promise will be executed immediately when it is constructed, the above code is defined in the way of const p = function(){return new Promise()}, so as to meet the requirement of execution when it needs to be called.

        async, await handle multiple asynchronous processes:

const getUp = function () {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log('get up at 7:00.')
                    resolve();
                }, 100);
            });
        }
        const washFace = function () {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log('wash face at 7:10.')
                    resolve();
                }, 100);
            });
        }
        const brushTeeth = function () {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log('brush teeth at 7:20.')
                    resolve();
                }, 100);
            });
        }
        const haveBreakfast = function () {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log('have breakfast at 7:30.')
                    resolve();
                }, 100);
            });
        }
        const goToWork = function () {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log('go to work at 8:00.')
                    resolve();
                }, 100);
            });
        }
        const happyDay = async function () {
            await getUp();
            await washFace();
            await brushTeeth();
            await haveBreakfast();
            await goToWork();
        }
        happyDay();

        operation result:

        Comparing the code method, it is obvious that the async and await methods are more concise and easy to read. 

 

Guess you like

Origin blog.csdn.net/evanyanglibo/article/details/125386139