ES6 class类

417 阅读3分钟

在这里就先不论述class的创建方式和继承方法,只是挑出几个知识点来记录一下。

静态方法和静态属性

静态的是指向类自身,而不是指向实例对象

静态方法

如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。

  1. 如果静态方法包含this关键字,这个this指的是类,而不是实例
  2. 虽然既然类的静态方法不可被实例所继承,但是却可以被子类继承
  3. 可以从super对象上调用
     class F {
            static classMethod() {
                // console.log(this)
                return "hello"
            }
        }

        class C extends F {
            constructor() {
                super()
            }
        }

        console.log(F.classMethod())
        console.log(C.classMethod())
    class F {
            static classMethod() {
                    return "hello"
                }
        }

        class C extends F {
            static Fn() {
                return super.classMethod() + "too"
            }
        }
        console.log(C.Fn())

静态属性

静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性。

class Foo {
}

Foo.prop = 1;
Foo.prop // 1

目前,只有这种写法可行,因为 ES6 明确规定,Class 内部只有静态方法,没有静态属性。 现在有一个提案提供了类的静态属性,写法是在实例属性法的前面,加上static关键字。

// 老写法
class Foo {
  // ...
}
Foo.prop = 1;

// 新写法
class Foo {
  static prop = 1;
}

实例方法和实例属性

实例方法其实就是相当于都定义在了prototype原型上;
实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)。

        class Point {
            constructor(x, y) {
                //实例属性
                this.x = x;
                this.y = y;
            }

            toString() {
                //实例方法
                return '(' + this.x + ', ' + this.y + ')';
            }

        }

        var point = new Point(2, 3);

        point.toString() // (2, 3)

        //hasOwnProperty()返回一个布尔值,指示对象自身属性中是否具有指定的属性
        point.hasOwnProperty('x') // true
        point.hasOwnProperty('y') // true
        point.hasOwnProperty('toString') // false

super

super这个关键字,既可以当作函数使用,也可以当作对象使用;

super作为函数调用:

代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super函数。

class A {}

class B extends A {
  constructor() {
    super();
  }
}

子类B的构造函数之中的super(),代表调用父类的构造函数;
注意,super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B的实例,因此super()在这里相当于A.prototype.constructor.call(this)。

super作为对象:

在普通方法中,指向父类的原型对象;在静态方法中,指向父类。

class A {
  p() {
    return 2;
  }
}

class B extends A {
  constructor() {
    super();
    console.log(super.p()); // 2
  }
}

let b = new B();

上面代码中,子类B当中的super.p(),就是将super当作一个对象使用。这时,super在普通方法之中,指向A.prototype,所以super.p()就相当于A.prototype.p()。
这里需要注意,由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。

class A {
  constructor() {
    this.p = 2;
  }
}

class B extends A {
  get m() {
    return super.p;
  }
}

let b = new B();
b.m // undefined

如果属性定义在父类的原型对象上,super就可以取到。

class A {}
A.prototype.x = 2;

class B extends A {
  constructor() {
    super();
    console.log(super.x) // 2
  }
}

let b = new B();

ES6 规定,在子类普通方法中通过super调用父类的方法时,方法内部的this指向当前的子类实例。


如果super作为对象,用在静态方法之中,这时super将指向父类,而不是父类的原型对象。

class Parent {
  static myMethod(msg) {
    console.log('static', msg);
  }

  myMethod(msg) {
    console.log('instance', msg);
  }
}

class Child extends Parent {
  static myMethod(msg) {
    super.myMethod(msg);
  }

  myMethod(msg) {
    super.myMethod(msg);
  }
}

Child.myMethod(1); // static 1

var child = new Child();
child.myMethod(2); // instance 2