美文网首页
ES6 class 的继承

ES6 class 的继承

作者: Cherry丶小丸子 | 来源:发表于2022-03-15 20:09 被阅读0次
简介

Class 可以通过 extends 关键字实现继承,让子类继承父类的属性和方法。extends 的写法比 ES5 的原型链继承,要清晰和方便很多

class Point {}

class ColorPoint extends Point {}

`上面示例中,Point是父类,ColorPoint是子类,它通过 extends 关键字,继承了 Point 类的所有属性和方法。
但是由于没有部署任何代码,所以这两个类完全一样,等于复制了一个 Point 类`

下面,我们在ColorPoint内部加上代码

class Point { /* ... */ }

class ColorPoint extends Point {
    constructor(x, y, color) {
        super(x, y); // 调用父类的 constructor(x, y)
        this.color = color;
    }

    toString() {
        return this.color + ' ' + super.toString(); // 调用父类的 toString()
    }
}
constructor() 方法和 toString() 方法内部,都出现了 super 关键字。super 在这里表示父类的构造函数,用来新建一个父类的实例对象

ES6 规定,子类必须在 constructor() 方法中调用 super(),否则就会报错,这是因为子类自己的 this 对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,添加子类自己的实例属性和方法。如果不调用 super() 方法,子类就得不到自己的 this 对象

另一个需要注意的地方是,在子类的构造函数中,只有调用 super() 之后,才可以使用 this 关键字,否则会报错。这是因为子类实例的构建,必须先完成父类的继承,只有 super() 方法才能让子类实例继承父类

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
}

class ColorPoint extends Point {
    constructor(x, y, color) {
        this.color = color; // ReferenceError
        super(x, y);
        this.color = color; // 正确
    }
}

如果子类没有定义 constructor() 方法,这个方法会默认添加,并且里面会调用 super()。也就是说,不管有没有显式定义,任何一个子类都有 constructor() 方法

class ColorPoint extends Point {}

// 等同于
class ColorPoint extends Point {
    constructor(...args) {
        super(...args);
    }
}

有了子类的定义,就可以生成子类的实例了

let cp = new ColorPoint(25, 8, 'green');

cp instanceof ColorPoint // true
cp instanceof Point // true
上面示例中,实例对象 cp 同时是 ColorPoint 和 Point 两个类的实例,这与 ES5 的行为完全一致

除了私有属性,父类的所有属性和方法,都会被子类继承,其中包括静态方法

class A {
    static hello() {
        console.log('hello world');
    }
}

class B extends A {}

B.hello()  // hello world

子类无法继承父类的私有属性,或者说,私有属性只能在定义它的 class 里面使用

class Foo {
    #p = 1;
    #m() {
        console.log('hello');
    }
}

class Bar extends Foo {
    constructor() {
        super();
        console.log(this.#p); // 报错
        this.#m(); // 报错
    }
}

如果父类定义了私有属性的读写方法,子类就可以通过这些方法,读写私有属性

class Foo {
    #p = 1;
    getP() {
        return this.#p;
    }
}

class Bar extends Foo {
    constructor() {
        super();
        console.log(this.getP()); // 1
    }
}

super 关键字

super 这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同

第一种情况,super 作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次 super 函数
class A {}

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

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

class A {}

class B extends A {
    m() {
        super(); // 报错
    }
}

上面代码中,super() 用在 B 类的 m 方法之中,就会造成语法错误
第二种情况,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

上面代码中,p 是父类 A 实例的属性,super.p 就引用不到它

如果属性定义在父类的原型对象上,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 调用父类的方法时,方法内部的 this 指向当前的子类,而不是子类的实例

相关文章

  • react组件

    es6 的class类的继承 运用es6 class继承 通过继承React.Component类来定义一个组件

  • [JavaScript] class

    ES6中的class基于原型继承创建类。 (1)class只是原型继承的语法糖 相当于: 注: class定义中...

  • JavaScript继承

    es6继承 class Square extends Polygon {constructor(length) {...

  • JavaScript ES6 class多重继承实践与总结

    ES6中,class原生是不支持多重继承的,根据阮一峰ES6参考资料中的方法,通过以下方式即可实现class继承多...

  • ES6

    ES6是一个语言标准,不是一个框架。 ES6中的class与继承 class是创建类对象与实现类继承的语法糖,旨在...

  • Javascript原型和原型链

    JavaScript在ES6之前没有类似class,extend的继承机制,JavaScript的继承主要是通过原...

  • JS中类的继承封装和多态

    子类继承父类的属性和方法(原生继承,call继承,寄生组合继承,ES6中class类继承)原生继承:让子类的原型指...

  • ES6新特性

    ES6新特性 1.类(支持继承 extends)class TestClass { constructor(...

  • ES6中的class继承

    ES6中的class继承 Son(constructor function)的隐式原型proto指向Father(...

  • ES5和ES6 实现继承方式

    在ES5 中:通过原型链实现继承的,常见的继承方式是组合继承和寄生组合继承;在ES6中:通过Class来继承 组合...

网友评论

      本文标题:ES6 class 的继承

      本文链接:https://www.haomeiwen.com/subject/swgydrtx.html