ES6

作者: 他在发呆 | 来源:发表于2016-11-23 14:56 被阅读0次

    ECMAScript 6,也叫 ES6 或 ES2015。

    JavaScript 自 1995 年面世,1997 年成立的 ECMAScript 引领着 JavaScript 的发展。已发布的版本 ES3、 ES5、 ES6 。

    • JavaScript 进化史

    ES3 与 ES5 之间隔了 10 年,而ES5 与 ES6 之间隔了 6 年。改进的新模式是每年都渐进式地做一些小改动,而不是像 ES6 一样一次性地进行大量的更改。

    • 浏览器支持

    大部分都已可以使用

    ES6 新增优势

    • 块级作用域变量let const

    var 定义的变量会泄露到其它代码块,比如 for 循环或是 if 块。

    (详见let和const语法)

    • IIFE

    在ES5中

    
    {
    
     var private = 1;
    
    }
    
    console.log(private); // 1
    

    private 会发生泄漏。需要使用 IIFE(立即执行函数表达式)将其包起来:

    
    (function(){
    
     var private2 = 1;
    
    })();
    
    console.log(private2); // Uncaught ReferenceError
    

    jQuery等开源项目的源代码,它们都利用了 IIFE,以避免污染全局环境,而只在全局下定义 _、$或是 jQuery。

    而在ES6中

    {
    
     let private3 = 1;
    
    }
    
    console.log(private3); // Uncaught ReferenceError
    

    Const表示定义了一个常量,更改值,会报错

    • 文本模板

    ES5

    
    var first = 'Adrian';
    
    var last = 'Mejia';
    
    console.log('Your name is ' + first + ' ' + last + '.');
    

    ES6可以用 反引号 和字符串插值 ${}:

    const first = 'Adrian';
    
    const last = 'Mejia';
    
    console.log(`Your name is ${first} ${last}.`);
    
    • 多行字符串也同样可以使用反引号连接

    • ES6 解构非常简明并且好用

    ES5

    var array = [1, 2, 3, 4];
    
    var first = array[0];
    
    var third = array[2];
    
    console.log(first, third); // 1 3
    

    等同于:

    ES6

    const array = [1, 2, 3, 4];
    
    const [first, ,third] = array;
    
    console.log(first, third); // 1 3
    
    • 调换值

    ES5

    var a = 1;
    
    var b = 2;
    
    var tmp = a;
    
    a = b;
    
    b = tmp;
    
    console.log(a, b); // 2 1
    

    等同于

    ES6

    let a = 1;
    
    let b = 2;
    
    [a, b] = [b, a];
    
    console.log(a, b); // 2 1
    
    • 返回多个值

    ES5

    function margin() {
    
     var left=1, right=2, top=3, bottom=4;
    
     return { left: left, right: right, top: top, bottom: bottom };
    
    }
    
    var data = margin();
    
    var left = data.left;
    
    var bottom = data.bottom;
    
    console.log(left, bottom); // 1 4
    
    在第3行,也可以像这样用数组返回(并保存序列):
    
    return [left, right, top, bottom];
    
    但之后调用时需要考虑返回数据的顺序。
    
    var left = data[0];
    
    var bottom = data[3];
    

    ES6 中调用时只会选择需要的数据(第 6 行):

    1. function margin() {
    
    2  const left=1, right=2, top=3, bottom=4;
    
    3  return { left, right, top, bottom };
    
    4 }
    
    5 const { left, bottom } = margin();
    
    6 console.log(left, bottom); // 1 4
    
    
    

    注意:第3行用到了一些其它的 ES6 功能。可以将 { left: left } 简化为 { left }.

    参数匹配解构

    ES5

    var user = {firstName: 'Adrian', lastName: 'Mejia'};
    
    function getFullName(user) {
    
     var firstName = user.firstName;
    
     var lastName = user.lastName;
    
     return firstName + ' ' + lastName;
    
    }
    
    console.log(getFullName(user)); // Adrian Mejia
    
    

    ES6

    const user = {firstName: 'Adrian', lastName: 'Mejia'};
    
    function getFullName({ firstName, lastName }) {
    
     return `${firstName} ${lastName}`;
    
    }
    
    console.log(getFullName(user)); // Adrian Mejia
    

    深度匹配

    ES5

    function settings() {
    
     return { display: { color: 'red' }, keyboard: { layout: 'querty'} };
    
    }
    
    var tmp = settings();
    
    var displayColor = tmp.display.color;
    
    var keyboardLayout = tmp.keyboard.layout;
    
    console.log(displayColor, keyboardLayout); // red querty
    
    
    

    ES6

    function settings() {
    
     return { display: { color: 'red' }, keyboard: { layout: 'querty'} };
    
    }
    
    const { display: { color: displayColor }, keyboard: { layout: keyboardLayout }} = settings();
    
    console.log(displayColor, keyboardLayout); // red querty
    

    使用数组解构获取元素或调换变量,这样就不用创建临时引用了。

    对于多返回值的情况,不要用数组解构,用对象解构。

    • 类和对象

    ES6 用“类”替代“构造函数”。

    在 JavaScript 中,每个对象都有原型对象。所有 JavaScript 对象都从原型上继承方法和属性。

    ES5 以面向对象编程的方式创建对象,是利用构造函数实现的:

    ES5

    var Animal = (function () {
    
     function MyConstructor(name) {
    
       this.name = name;
    
     }
    
     MyConstructor.prototype.speak = function speak() {
    
       console.log(this.name + ' makes a noise.');
    
     };
    
     return MyConstructor;
    
    })();
    
    var animal = new Animal('animal');
    
    animal.speak(); // animal makes a noise.
    

    ES6 可以用 class、constructor 等新的关键字、更少的样板代码实现相同的效果。同样可以看到相比于constructor.prototype.speak = function (),用 speak() 定义方法更加清晰:

    ES6

    class Animal {
    
     constructor(name) {
    
       this.name = name;
    
     }
    
     speak() {
    
       console.log(this.name + ' makes a noise.');
    
     }
    
    }
    
    const animal = new Animal('animal');
    
    animal.speak(); // animal makes a noise.
    

    用 class 语法,避免直接操作 prototype.

    避免出现空的构造器。如果没有指明,类会有默认的构造器的。

    • 继承

    基于前面的 Animal 类,现在想要拓展 Animal,定义一个 Lion 类。

    ES5

    var Lion = (function () {
    
     function MyConstructor(name){
    
       Animal.call(this, name);
    
     }
    
     MyConstructor.prototype = Object.create(Animal.prototype);
    
     MyConstructor.prototype.constructor = Animal;
    
     MyConstructor.prototype.speak = function speak() {
    
       Animal.prototype.speak.call(this);
    
       console.log(this.name + ' roars ');
    
     };
    
     return MyConstructor;
    
    })();
    
    var lion = new Lion('Simba');
    
    lion.speak(); // Simba makes a noise.
    
    // Simba roars.
    

    ES6

    class Lion extends Animal {
    
     speak() {
    
       super.speak();
    
       console.log(this.name + ' roars ');
    
     }
    
    }
    
    const lion = new Lion('Simba');
    
    lion.speak(); // Simba makes a noise.
    
    // Simba roars.
    
    
    

    使用内置的 extends 实现继承。

    原生 Promise

    用 promise 替代回调地狱

    ES5

    function printAfterTimeout(string, timeout, done){
    
     setTimeout(function(){
    
       done(string);
    
     }, timeout);
    
    }
    
    printAfterTimeout('Hello ', 2000, function(result){
    
     console.log(result);
    
     // nested callback
    
     printAfterTimeout(result + 'Reader', 2000, function(result){
    
       console.log(result);
    
     });
    
    });
    
    

    这个函数接收一个回调,在 done 后执行。我们想要先后执行两次,所以在回调中又一次调用了 printAfterTimeout。

    如果需要多次回调。用 promise 实现

    ES6

    function printAfterTimeout(string, timeout){
    
     return new Promise((resolve, reject) => {
    
       setTimeout(function(){
    
         resolve(string);
    
       }, timeout);
    
     });
    
    }
    
    printAfterTimeout('Hello ', 2000).then((result) => {
    
     console.log(result);
    
     return printAfterTimeout(result + 'Reader', 2000);
    
    }).then((result) => {
    
     console.log(result);
    
    });
    
    • 箭头函数

    ES6 没有移除函数表达式,但是新增了箭头函数。

    ES5 this的指向

    var _this = this; // 
    
    $('.btn').click(function(event){
    
     _this.sendData(); // reference outer this
    
    });
    
    $('.input').on('change',function(event){
    
     this.sendData(); // reference outer this
    
    }.bind(this)); // bind to outer this
    

    在函数内,需要用临时变量指向 this 或者使用 bind 绑定。ES6 中可以使用箭头函数。

    For…of

    最开始用 for ,然后使用 forEach,而现在可以用 for…of:

    ES6

    
    $('.btn').click((event) =>  this.sendData());
    
    // implicit returns
    
    const ids = [291, 288, 984];
    
    const messages = ids.map(value => `ID is ${value}`);
    
    

    ES6 的 for…of 也可以用来迭代。

    默认参数

    之前需要检测变量是否定义了,而现在可以指定 default parameters 的值。

    ES5

    function point(x, y, isFlag){
    
     x = x || 0;
    
     y = y || -1;
    
     isFlag = isFlag || true;
    
     console.log(x,y, isFlag);
    
    }
    
    point(0, 0) // 0 -1 true//我们传的值是 0, 0 但是得到的是 0, -1
    
    
    point(0, 0, false) // 0 -1 true//传进去 false 但是得到的是 true。
    
    point(1) // 1 -1 true
    
    point() // 0 -1 true
    
    

    这可能是检测变量有值或指定默认值的惯用模式,但也存在一些问题:

    ES6

    function point(x = 0, y = -1, isFlag = true){
    
     console.log(x,y, isFlag);
    
    }
    
    
    point(0, 0) // 0 0 true
    
    
    point(0, 0, false) // 0 0 false
    
    
    point(1) // 1 -1 true
    
    
    point() // 0 -1 true
    
    

    ES5 是因为先要检测 undefined的值,而 false、 null、 undefined 和 0 都是假的值。我们可以加些代码:

    ES5

    function point(x, y, isFlag){
    
     x = x || 0;
    
     y = typeof(y) === 'undefined' ? -1 : y;
    
     isFlag = typeof(isFlag) === 'undefined' ? true : isFlag;
    
     console.log(x,y, isFlag);
    
    }
    
    point(0, 0) // 0 0 true
    
    point(0, 0, false) // 0 0 false
    
    point(1) // 1 -1 true
    
    point() // 0 -1 true
    
    

    现在当检测 undefined 值时就符合我们的要求了。

    之前使用 arguments,而现在可以用展开操作符。

    现在可以用展开操作符 ... 达到相同的目的。

    ES6

    function printf(format, ...params) {
    
     console.log('params: ', params);
    
     console.log('format: ', format);
    
    }
    
    printf('%s %d %.2f', 'adrian', 321, Math.PI);
    

    展开操作符...

    之前用 apply(),现在可以方便地使用展开操作符 ... 了:

    提示:apply() 可以将数组转化为一系列参数。例如 Math.max() 接收一系列参数,但如果想应用于数组的话可以用 apply 帮助实现。

    如上所述,apply 可以将数组当作参数序列进行传递:

    ES5

    Math.max.apply(Math, [2,100,1,6,43]) // 100
    

    ES6 可以用展开操作符:

    ES6

    ```
    Math.max(...[2,100,1,6,43]) // 100

    
    
     concat 合并数组,现在也可以用展开操作符:
    
    ES5
    
    

    var array1 = [2,100,1,6,43];

    var array2 = ['a', 'b', 'c', 'd'];

    var array3 = [false, true, null, undefined];

    console.log(array1.concat(array2, array3));

    
    ES6 可以用展开操作符展开嵌套的数组:
    
    ES6
    
    
    > 
    const array1 = [2,100,1,6,43];
    
    > const array2 = ['a', 'b', 'c', 'd'];
    
    > const array3 = [false, true, null, undefined];
    
    > console.log([...array1, ...array2, ...array3])

    相关文章

      网友评论

          本文标题:ES6

          本文链接:https://www.haomeiwen.com/subject/deqvpttx.html