ES6-常用知识

ES6相关

  • let、const与var相比

    使用未声明的变量,直接报错
    重复声明同一个变量,直接报错
    是块级作用域
    必须声明 ‘use strict’ 后才能使用let声明变量

  • 数组的解构赋值,是值的拷贝,不是深拷贝

  • 对象的解构赋值,是值的拷贝,不是深拷贝,let {a: { b }} = {a: { b: 1 }} 给b赋值,此时a是未定义的
  • 箭头函数

    (1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
    (2)不可以当作构造函数,也就是不可以使用new命令,否则会抛出错误。
    (3)不可以使用arguments对象,该对象在函数体内不存在,如果要用,可以使用rest参数代替。
    (4)不可以使用yield命令,因为箭头函数不能用作Generator函数。

    理解定义时所在的作用域。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    var obj = {
    a: 1,
    fn: function () {console.log(this.a)}
    };
    obj.fn(); // 1
    var obj = {
    a: 1,
    fn: () => {console.log(this.a)}
    };
    obj.fn(); // undefined
    var obj = {
    a: 1,
    fn: function () {
    setTimeout(() => {console.log(this.a)}, 0)
    }
    };
    obj.fn(); // 1
    var obj = {
    a: 1,
    fn: function () {console.log(this.a)}
    };
    setTimeout(obj.fn, 0); // undefined
    var obj = {
    a: 1,
    fn: () => {console.log(this.a)}
    };
    setTimeout(obj.fn, 0); // undefined
  • super

    super关键字,既可以当作函数使用,也可以当作对象使用。使用super的时候,必须显式指定是作为函数、还是作为对象使用,否则会报错。由于对象总是继承其他对象的,所以可以在任意一个对象中,使用super关键字。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class A {}
    class B extends A {
    constructor() {
    super();
    /*
    Uncaught SyntaxError: 'super' keyword unexpected here
    无法看出super是作为函数使用,还是作为对象使用
    */
    console.log(super);
    /*
    super.valueOf()表明super是一个对象
    */
    console.log(super.valueOf() instanceof B); // true
    }
    }
    var obj = {
    toString() {
    return "MyObject: " + super.toString();
    }
    };
    obj.toString(); // MyObject: [object Object]

    第一种情况,当作函数使用,代表父类的构造函数,super虽然代表了父类的构造函数,但是返回的是子类的实例,即super内部的this指的是子类。super()只能用在子类的构造函数中,用在其它地方就会报错。ES6要求,子类的构造函数必须执行一次super函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class A{}
    class B extends A {
    constructor() {
    /*
    当作函数使用,代表父类的构造函数,相当于
    A.prototype.constructor.call(this)
    */
    super();
    }
    }

    第二种情况,super作为对象时,在普通方法中指向父类的原型对象,在静态方法中指向父类。ES6规定,通过super调用父类的方法时,super会绑定子类的this。由于绑定子类的this,所以如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    class A {
    constructor() {
    this.q = 2;
    }
    p() {
    return 2;
    }
    print() {
    /*
    通过B的super.print()虽然调用的是A.prototype.print(),但是A.prototype.print()会绑定子类B的this,相当于
    super.print.call(this)
    */
    console.log(this.q);
    }
    }
    class B extends A {
    constructor() {
    super();
    this.q = 3;
    /*
    当作对象使用,这是普通方法,super指向A.prototype,相当于
    A.prototype.p()
    q是父类A实例的属性,super.q就引用不到它
    */
    console.log(super.p()); // 2
    console.log(super.q); // undefined
    }
    subPrint() {
    super.print();
    }
    }
    let b = new B();
    b.subPrint(); // 3
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class Parent {
    static myMethod(msg) {
    console.log('static', msg);
    }
    myMethod(msg) {
    console.log('instance', msg);
    }
    }
    class Child extends Parent {
    static myMethod(msg) {
    // 静态方法,super指向父类
    super.myMethod(msg);
    }
    myMethod(msg) {
    // 普通方法,super指向父类的原型对象
    super.myMethod(msg);
    }
    }
    Child.myMethod(1); // static 1
    var child = new Child();
    child.myMethod(2); // instance 2