Skip to content

Latest commit

 

History

History
139 lines (109 loc) · 4.1 KB

class.md

File metadata and controls

139 lines (109 loc) · 4.1 KB

Class

ES6以前,生成实例对象的方法是通过构造函数。

function Point(x,y){
    this.x = x
    this.y = y
}
Point.prototype.toString = function () {
    return '(' + this.x + ', ' + this.y + ')'
}
let p1 = new Point(1,1)

ES6中引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。

ES6中的类很大程度上只是构造函数的语法糖

class Point{
    constructor(x,y){
        this.x = x
        this.y = y
    }
    toString(){
        return '(' + this.x + ', ' + this.y + ')';
    }
}
let p1 = new Point(1,1)

虽然class Point看起来很像function Point(),但是有一些重要的区别:

  • 使用class创建实例对象必须通过new,构造函数可以通过Point.call(...)
  • 虽然function Point会被“提升”,但是class Point不会;所以,在你创建类实例之前必须先声明它。

类中定义的所有方法都是在类的prototype上定义的

使用class时,可以将它作为一个用来自动填充proptotype对象的

class Point {
  constructor() {
    // ...
  }

  toString() {
    // ...
  }

  toValue() {
    // ...
  }
}

// 等同于

Point.prototype = {
  constructor() {},
  toString() {},
  toValue() {},
};

其实一个ES6 class本身不是一个实体,而是一个元概念,它包裹在其他具体实体上,例如函数和属性,并将它们绑在一起。

constructor

constructor是类的默认方法,使用new命令生成实例时会自动调用该方法。

这个方法的明确的工作,就是初始化实例所需的所有信息(状态)。

通常在constructor中对实例对象的属性进行初始化。

constructor方法默认返回实例对象(即this

this指向

和构造函数创建实例一样,this指向实例对象

类的方法内部如果含有this,它默认指向类的实例。

extends&super

Class 可以通过extends关键字实现继承

extends实质上也是一种语法糖,用于在两个函数原型之间建立[[Prototype]]委托链

class Point {
}
class ColorPoint extends Point {
}

上面代码定义了一个ColorPoint类,该类通过extends关键字,继承了Point类的所有属性和方法。

或者说是ColorPoint.prototype[[prototype]](大多数浏览器通过__proto__访问)链接到Point.prototype

子类必须在constructor方法中调用super方法,否则新建实例时会报错。

这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。

如果不调用super方法,子类就得不到this对象。

ES5 :实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。

ES6 :实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this

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

  • super作为函数调用时,代表父类的构造函数。

    class A {
        constructor() {
            console.log(new.target.name);
        }
    }
    class B extends A {
        constructor() {
            super();
        }
    }
    new A() // A
    new B() // B

    上面代码中,new.target指向当前正在执行的函数。可以看到,在super()执行时,它指向的是子类B的构造函数,而不是父类A的构造函数。也就是说,super()内部的this指向的是B

    作为函数时,super()只能用在子类的构造函数之中,用在其他地方就会报错。

  • super作为对象时,指向父类的原型对象

    class A {
        p() {
            return 2;
        }
    }
    
    class B extends A {
        constructor() {
            super();
            console.log(super.p()); // 2
        }
    }
    
    let b = new B();

上面的super.p()相当于A.prototype.p()