在这里就先不论述class的创建方式和继承方法,只是挑出几个知识点来记录一下。
静态方法和静态属性
静态的是指向类自身,而不是指向实例对象
静态方法
如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
- 如果静态方法包含this关键字,这个this指的是类,而不是实例
- 虽然既然类的静态方法不可被实例所继承,但是却可以被子类继承
- 可以从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