FrankKai.github.io
FrankKai.github.io copied to clipboard
es6 class 之 super
class在面向对象设计中非常有用,super关键字值得好好学习一下。
- super关键字概览
- 初识
- 语法
- 描述
- super关键字常用示例
- 在constructor中使用super(super(args0,args1))
- 使用super调用static方法(super.staticMethod())
- 删除super属性会抛出错误(delete super.foo error)
- super.prop不能重写非可写属性(object的writable为false)
- 在object 迭代过程中使用super.prop(super不仅仅适用于class,在object中也可以使用)
- super实践疑惑
- 印象中java可以直接super,es6的class可以直接super()吗?
- 可以不在constructor中调用
super()
,直接使用super.xxx()吗? - 到底要将super()理解成什么?
super关键字概览
初识
super关键字用于调用对象的父对象的函数。
super.prop
和super[expr]
表达式对于classed和object literals方法定义都是有效的。
语法
super([arguments]); // 调用parent的constructor
super.functionOnParent([arguments]);
描述
在使用constructor时,super关键字单独出现而且必须要在this关键词之前使用。 super同样可以调用父对象的函数。
super关键字常用示例
在constructor中使用super
下面的例子使用super()关键词为Square继承了Rectangle构造器中的属性。
class Rectangle {
constructor(height, width) {
this.name = 'Rectangle';
this.height = height;
this.width = width;
}
...
}
class Square extends Rectangle {
constructor(length) {
this.height; // ReferenceError, super needs to be called first!
super(length, length);
this.name = 'Square';
}
}
使用super调用static方法
可以使用super.xxx()调用父class的static方法。
class Rectangle {
constructor() {}
static logNbSides() {
return 'I have 4 sides';
}
}
class Square extends Rectangle {
constructor() {}
static logDescription() {
return super.logNbSides() + ' which are all equal';
}
}
Square.logDescription(); // 'I have 4 sides which are all equal'
删除super属性会抛出错误
不能用delete操作符删除super.prop或super[expr],会抛出一个ReferenceError。
class Base {
constructor() {}
foo() {}
}
class Derived extends Base {
constructor() {}
delete() {
delete super.foo; // this is bad
}
}
new Derived().delete(); // ReferenceError: invalid delete involving 'super'.
super.prop无法重写非writable的属性
当使用Object.defineProperty定义一个非可写属性时,super不能重写这个值。
class X {
constructor() {
// 这里定义了一个read-only的prop属性
Object.defineProperty(this, 'prop', {
configurable: true,
writable: false,
value: 1
});
}
}
class Y extends X {
constructor() {
super();
}
foo() {
super.prop = 2; // Cannot overwrite the value.
}
}
var y = new Y();
y.foo(); // TypeError: "prop" is read-only
console.log(y.prop); // 1
在object 迭代过程中使用super.prop
super不仅仅在class中使用,在object中也可以使用。 需要使用Object.setPrototypeOf。
var obj1 = {
method1() {
console.log('method1');
}
}
var obj2 = {
method2() {
super.method1(); // 惊不惊喜,对象也能用super
}
}
Object.setPrototypeOf(obj2, obj1);
obj2.method2(); // 打印出"method1"
super实践疑惑
印象中java可以直接super,es6的class可以直接super()吗?
看看下面这个例子。
super(); // 仅继承父的prototype method
super(prop1, prop2); // 继承父的constructor和prototype method
可以是可以。 但是不会继承父constructor,只会继承父的prototype方法。 所以最好还是写上要继承哪个prop。
需要做以下几步:
1.子class的constructor传入自己的入参,constructor(prop1,prop2)
2.在super中指明要继承父class的属性,super(prop1,prop2,...)
。
class Base {
constructor(name, age) {
this.name = name;
this.age = age;
}
foo(){
console.log("Hi, I'm foo");
}
}
class Sub extends Base {
constructor(name, age){
// super(); wrong 若是这样,未继承父的this.name = name
super(name); // right 这样才对,继承了父的this.name = name
console.log(this.name); // 打印出名字。
super.foo(); // 无论是super(),还是super(name)。都可以打印出foo
}
}
var foo = new Sub('gaokai', 25);
可以不在constructor中调用super()
,直接使用super.xxx()吗?
不可以。 若你这样做了,会报下面这样的错。
class Sub extends Base {
constructor(name, age){
super.foo();
}
}
ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
到底要将super()
理解成什么?
有人说super()
可以理解成ParentClass.constructor()
,是这样吗?
只说对了一半。
super()可以理解为下面两部分的集合:
-
继承
ParentClass.constructor()
- super包含父parent class的prototype方法集
static方法可以通过super获取到吗?不能。 public定义的变量可以通过super获取到吗?不能。
所以我们一般都是使用super(foo,bar)
这样的形式。
调用之后它做到了:
- 继承了父class的constructor到当前class,
ParentClass.constructor(foo, bar)
。 - super中包含父class中的prototype方法集。
参考资料:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super