JavaScript-constructor和extends以及static

48 阅读3分钟

构造方法

constructor是一种用于创建和初始化class创建的对象的特殊方法。 示例:

class Polygon {
    constructor(height, width) {
        this.height = height;
        this.width = width;
        this.name = "Polygon";
    }
}
let p1 = new Polygon();
console.log(p1); // Polygon 

语法

constrcutor([arguments]) {...}

描述

在一个类中只能有一个名为"constructor"的特殊方法。一个类中出现多次构造函数(constructor)方法将会抛出一个SyntaxError错误。

在一个构造方法中可以使用super关键字来调用一个父类的构造方法。

如果没有显式指定构造方法,则会添加默认的constructor方法。

如果不指定一个构造函数(constructor)方法,则使用一个默认的构造函数(constructor)。

示例

class Square extends Polygon {
    constructor(length) {
        // 在这里,它调用了父类的构造函数,并将lengths提供给Polygon的“width”和“height”
        super(length,length);
        // 注意:在派生类中,必须先调用super(),才能使用“this”。
        // 忽略这个,将会导致一个引用错误。
        this.name = 'Square';
    }
    get area() {
        return this.height * this.width;
    }
    set area(value) {
        // 注意:不可使用this.area = value
        // 否则会导致循环 call setter 方法导致爆栈
        this._area = value;
    }
}

另一个例子

class Polygon {
    constructor() {
        this.name = "Polygon";
    }
}

class Square extends Polygon {
    constructor() {
        super();
    }
}

class Rectangle {}

Object.setPrototypeOf(Square.prototype, Rectangle.prototype); // 替换原型对象

console.log(Object.getPrototypeOf(Square.prototype) === Polygon.prototype); //false
console.log(Object.getPrototypeOf(Square.prototype) === Rectangle.prototype); //true

let newInstance = new Square();
console.log(newInstance.name); //Polygon

这里,Square类的原型被改变,但是在正在创建一个新的正方形实例时,仍然调用前一个基类Polygon的构造函数。

默认构造方法

如前所述,如果不指定构造方法,则使用默认构造函数。对于基类,默认构造函数是:

constructor() {}

对于派生类,默认构造函数是:

constructor(...args) {
    super(...args);
}

extends

extends关键字用于类声明或者类表达式中,以创建一个类,该类是另一个类的子类。

语法

class ChildClass extends ParentClass { ... }

描述

extends关键字用来创建一个普通类或者内建对象的子类。 继承的.prototype必须是一个Object或者null

示例

使用extends

class Base {
    constructor(name){
        this.name = name;
    }
};

class A extends Base {
    constructor(name) {
        super(name);
        this.name = 'A';
    }
}

使用extends与内内置对象

这个示例继承了内置的Date对象。

class myDate extends Date {
    constructor() {
        super();
    }
    getFormattedDate() {
        var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
        return this.getDate() + "-" + months[this.getMonth()] + "-" + this.getFullYear();
    }
}
let m1 = new myDate();
console.log(m1.getFormattedDate()); // 29-Mar-2023

扩展null

可以像扩展普通类一样扩展null,但是新对象的原型将不会继承Object.prototype

class nullExtends extends null {
  constructor() {}
}

Object.getPrototypeOf(nullExtends); // Function.prototype
Object.getPrototypeOf(nullExtends.prototype) // null

new nullExtends(); //ReferenceError: this is not defined

static

类(class)通过 static 关键字定义静态方法。不能在类的实例上调用静态方法,而应该通过类本身调用。这些通常是实用程序方法,例如创建或克隆对象的功能。

示例

下面的例子说明了这几点:

  1. 静态方法如何在类上实现。
  2. 具有静态成员的类,可以被子类化。
  3. 什么情况下静态方法可以调用,什么情况下不能调用。
class Tripple {
  static tripple(n = 1) {
    return n * 3;
  }
}


class BiggerTripple extends Tripple {
  static tripple(n) {
    return super.tripple(n) * super.tripple(n);
  }
}


console.log(Tripple.tripple()); // 3
console.log(Tripple.tripple(6)); // 18

let tp = new Tripple();

console.log(BiggerTripple.tripple(3)); // 81(不会受父类实例化的影响)
console.log(tp.tripple()); // 'tp.tripple 不是一个函数'.