Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

es6 class 之 super #202

Open
FrankKai opened this issue Apr 3, 2020 · 0 comments
Open

es6 class 之 super #202

FrankKai opened this issue Apr 3, 2020 · 0 comments

Comments

@FrankKai
Copy link
Owner

FrankKai commented Apr 3, 2020

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.propsuper[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()可以理解为下面两部分的集合:

  1. 继承ParentClass.constructor()
  2. super包含父parent class的prototype方法集

static方法可以通过super获取到吗?不能。
public定义的变量可以通过super获取到吗?不能。

所以我们一般都是使用super(foo,bar)这样的形式。
调用之后它做到了:

  1. 继承了父class的constructor到当前class,ParentClass.constructor(foo, bar)
  2. super中包含父class中的prototype方法集。

参考资料:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant