美文网首页
读《Why Do We Write super(props)》读

读《Why Do We Write super(props)》读

作者: 般犀 | 来源:发表于2018-12-14 10:13 被阅读0次

Why Do We Write super(props)
Redux 作者 Dan Abramov 发在博客的一篇文章。
早上逛掘金发现已经有译文:
【译】为何我们要写super(props)?

想想要总结下写下读后感,才算没白读。

总结几点印象比较深刻的:

  • 为什么要在使用 this 前调用super() ?
    考虑这样的场景:
class Person {
  constructor(name) {
    this.name = name;
  }
}

class PolitePerson extends Person {
  constructor(name) {
    this.greetColleagues(); // 🔴 This is disallowed, read below why
    super(name);
  }
  greetColleagues() {
    alert('Good morning folks!');
  }
}

假设我们允许在 super() 调用前调用 this,我们在子类调用了继承自父类的方法,这样做似乎没什么问题。一个月后当我们想要更改我们的代码:

greetColleagues() {
    alert('Good morning folks!');
    alert('My name is ' + this.name + ', nice to meet you!');
  }

因为我们在调用 super前调用了 this.greetColleagues,而 this.name 需要在调用了 super之后才被实例化,所以此时 this.name 将是未定义的!
为了避免这样的情况发生,JS将 super必须在执行 this方法之前执行 作为强制规定。

  • 为什么要在 super() 中传入 props?
    有些人认为只有给 super 传入 props ,React 才会帮你初始化 props
    这个答案很接近,实际上,即使你不在 super()里传入props,一样可以在 render函数里拿到 this.props,因为 React 已经帮你做了:
// Inside React
  const instance = new YourComponent(props);
  instance.props = props;

真正要传入 props 的原因是,如果不传入,你将无法在 super() 到 constructor 结束这个区间内拿到 this.props, this.props将是 undefined:

// Inside React
class Component {
  constructor(props) {
    this.props = props;
    // ...
  }
}

// Inside your code
class Button extends React.Component {
  constructor(props) {
    super(); // 😬 We forgot to pass props
    console.log(props);      // ✅ {}
    console.log(this.props); // 😬 undefined 
  }
  // ...
}

所以虽然给 super() 传入 props 不是必须的,但是为了避免出现不必要的 bug,建议总是传入 props 为好。

  • state 不一定要传入 constructor
    因为有了 class fields proposal(似乎是个新东西,要研究一下),所以我们不需要声明 constructor 即可声明 state
class Checkbox extends React.Component {
  state = { isOn: true };
  // ...
}

结合我的实践

想想以前工作的 时候如果声明了 constructor,我都不会传入 props,甚至因为 ts 的检查,为了让 super有值,我传入了 undefined...所以传入 props才是最佳实践。
还有最后的 state 声明方法,之前接了组里同事的代码后发现她就是这么写的,我竟然还想把他们改成 constructor 内声明,孤陋寡闻了...

关于 class fields proposal

看了下大概是对类内属性的声明发生了改变,在 ES6 中,类的属性必须在 constructor内声明,但新的方案让类的属性也可以直接在类的内部声明即可:

// ES6
class Counter extends HTMLElement {
  clicked() {
    this.x++;
    window.requestAnimationFrame(this.render.bind(this));
  }

  constructor() {
    super();
    this.onclick = this.clicked.bind(this);
    this.x = 0;
  }

  connectedCallback() { this.render(); }

  render() {
    this.textContent = this.x.toString();
  }
}
window.customElements.define('num-counter', Counter);
// Field declarations
class Counter extends HTMLElement {
  x = 0;

  clicked() {
    this.x++;
    window.requestAnimationFrame(this.render.bind(this));
  }

  constructor() {
    super();
    this.onclick = this.clicked.bind(this);
  }

  connectedCallback() { this.render(); }

  render() {
    this.textContent = this.x.toString();
  }
}
window.customElements.define('num-counter', Counter);

看到上面的示例我以为如果在 contructor 外声明的方法必须在 constructor 内做 this绑定,但是事实上在 constructor 外声明的方法, this 也是指向实例的。

相关文章

网友评论

      本文标题:读《Why Do We Write super(props)》读

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