我们之前在原型链中创建一个对象,需要使用函数的形式,然后在其原型中添加方法/属性,最后通过 new 关键字来创建实例。
那么在 ES6 之后,我们可以使用类的方式:
看上去确实清晰了很多。需要明确几点:
1、constructor 是一个构造函数,创建对象时会自动调用。即使你不写,它也默认存在。
2、所有写在 constructor 中的属性都是实例属性,是定义在实例中的。那么相对的,在 constructor 之外的属性,都是定义在类中的,也就是原型属性。
3、this 指向的是调用的实例对象,静态方法指向类本身。
4、子类使用构造器时,必须使用 super 关键字来扩展构造器,并且需要先调用 super。
6、使用 static 关键字标明类属性/方法,它们无法在实例中使用,而是通过类直接调用的。
为了深入理解,首先来看一下它们的原型结构:
看上去差不多,只是一个标记为函数,一个标记为类。
这也符合我们之前说过的原型方式,所以 class 本质上还是一个函数,只不过是一个语法糖,一个原型的另一种写法而已。
在此基础上,我们甚至可以通过原型的方式来修改/新增方法:
上面提到,constructor 属性内的是实例属性,之外的是原型属性,可以使用之前提到的检测方法来实践:
可以看到实例中自身只有 name 属性,而 print 方法确实在其原型链中可以被找到。
同时,静态属性/方法是会被继承的。
在继承过程中,经常会看到 super 关键字,它有两个作用:
1、子类调用构造函数 constructor 时,必须在构造函数内部先调用 super 关键字,然后才可以使用 this 对象。
2、子类同名方法会覆盖父类方法,这时使用 super 关键字可以调用父类方法。
所以需要在使用到 this 地方之前,调用一下 super。
作为对父类的扩展,有时候需要覆写父类,但是又需要用到父类的功能,这时可以在子类中使用 super 调用父类功能作为子类方法的一部分。
举一个例子,我们可以将上面的例子转换为:
从上面可以看到,其实 super 就是指向了原型,同时给我们提供了 this 的指向。
到此为止,基于JS的原型和原型链的内容基本就总结完毕了,学习 JS 一定要搞明白原型的内容。JS 的灵活之处就在于原型和原型链,其继承的方式也基于此,之后的类的概念也是在此基础上的。
总之,这段内容还是要多多练习领悟,才能通透。
