他们问我坚持了这么久是为了什么 ?
我说我没有坚持因为喜欢所以快乐
很多人一辈子忙忙碌碌不会懂得:
有个被嘲笑的梦想万一有天实现了呢?
类:就是对象的抽象。
对象:就是类的实例。
子类:继承自父类,又各有特长。龙生九子,各不成龙。
extends
关键词被用在类声明或者类表达式上,以创建一个类是另一个类的子类。实现继承,比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
使用extends
1 | class Square extends Polygon { |
根据Polygon类创建一个名为Square的类,也就是说,Square继承自Polygon。super
关键字,它在这里表示父类的构造函数,用来新建父类的this对象。
使用extends扩展内建对象
1 | class myDate extends Date { |
这个myDate继承自Date,并新增getFormattedDate方法。
注:只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,是基于对父类实例加工,只有super方法才能返回父类实例。
获取父类
Object.getPrototypeOf
方法可以用来从子类上获取父类。可以使用这个方法判断,一个类是否继承了另一个类。
super关键字
super
这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。
第一种情况,super作为函数调用时,代表父类的构造函数。ES6
要求,子类的构造函数必须执行一次super
函数。
super
虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super
内部的this
指的是B
,因此super()
在这里相当于A.prototype.constructor.call(this)
。
1 | class A { |
第二种情况,super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
1 | class A { |
上面代码中,子类B当中的super.p()
,就是将super
当作一个对象使用。这时,super
在普通方法之中,指向A.prototype
,所以super.p()
就相当于A.prototype.p()
。
这里需要注意,由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。
1 | class A { |
上面代码中,p是父类A实例的属性,super.p就引用不到它。
如果属性定义在父类的原型对象上,super就可以取到。
1 | class A {} |
上面代码中,属性x是定义在A.prototype上面的,所以super.x可以取到它的值。
ES6 规定,通过super调用父类的方法时,super会绑定子类的this。
1 | class A { |
上面代码中,super.print()虽然调用的是A.prototype.print(),但是A.prototype.print()会绑定子类B的this,导致输出的是2,而不是1。也就是说,实际上执行的是super.print.call(this)。
由于绑定子类的this,所以如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性。
1 | class A { |
上面代码中,super.x赋值为3,这时等同于对this.x赋值为3。而当读取super.x的时候,读的是A.prototype.x,所以返回undefined。
如果super作为对象,用在静态方法之中,这时super将指向父类,而不是父类的原型对象。
1 | class Parent { |
上面代码中,super在静态方法之中指向父类,在普通方法之中指向父类的原型对象。
参考
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/extends