精讀:爲何咱們要寫super(props)

在寫React時,咱們常常會寫下面這樣的組件:javascript

class Checkbox extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isOn: true };
  }
  // ...
}
複製代碼

有幾個問題須要值得咱們思考:java

爲何咱們要調用 super ? 咱們能不調用 super 嗎? 若是咱們必需要調用它,不傳 props 會發生什麼?它們還有其它參數嗎?react

在JavaScript中,super 指向了父級class 的 constructor,(例子中就是 React.Component的原型對象)。 你不能使用 this 在constructor中的 super 調用以前:git

class Checkbox extends React.Component {
  constructor(props) {
    // 這裏不能使用this
    super(props);
    // 如今這裏可使用this
    this.state = { isOn: true };
  }
  // ...
}
複製代碼

爲何 JavaScript 強制要求咱們調用 super, 在 constructor 中使用 this 前:github

class Person {
  constructor(name) {
    this.name = name;
  }
}

class PolitePerson extends Person {
  constructor(name) {
    this.greetColleagues(); // 這裏不容許咱們使用this,下面解釋
    super(name);
  }
  greetColleagues() {
    alert('Good morning folks!');
  }
}
複製代碼

上面的例子假設調用 super 以前容許使用 this, 一段時間後,咱們在 greetColleagues( ) 中添加:ui

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

可是咱們忘了,this.greetColleagues( ) 在 super 調用以前,this.name 都沒有定義,代碼會拋錯,像這樣的代碼可能很難想到何時發生。this

所以,爲了不這個陷阱,JavaScript 強制要求在 constructor 中使用 this 以前,必須先調用 super。 這個限制一樣也適用在 React Component 中,固然 class fidlds propsal 讓咱們也能夠經過一些方式來簡寫,不用這麼麻煩寫constructor( ):spa

class Checkbox extends React.Component {
  state = { isOn: true };
  // ...
}
複製代碼

爲何要傳遞props?debug

你可能會想,傳遞 props 給 super 是有必要的,這樣它繼承的 React.Component 的 constructor 就能初始化this.props:code

// 在React 內部
class Component {
  constructor(props) {
    this.props = props;
    // ...
  }
}
複製代碼

但它並不單單是爲了初始化 this.props, 從它的源碼裏解釋看能夠更新Component 狀態。實際上即便你調用super() 不傳props, 你仍然能訪問 this.props 在 render 或者其餘方法,這是由於在調用 constructor 後 React 能正確的分配 props 在實例對象上。

// React 內部
  const instance = new YourComponent(props);
  instance.props = props;
複製代碼

所以,即便你忘記傳 props 參數給 super( ), React 也會設置 props 能使你訪問。可是不是意味着咱們就不須要再傳 props 給 super?

並非,由於這樣容易由於混亂,儘管你的實例對象執行 constructor 後 React 會分配this.props ,但 this.props 還是 undefined。

// react 內部
class Component {
  constructor(props) {
    this.props = props;
    // ...
  }
}

// 你的代碼裏
class Button extends React.Component {
  constructor(props) {
    super(); // 咱們不傳 props
    console.log(props);      // {}
    console.log(this.props); // undefined 
  }
  // ...
}
複製代碼

這會給咱們 debug 帶來很大麻煩,React 仍是推薦咱們將props 傳遞 super:

class Button extends React.Component {
  constructor(props) {
    super(props); // 咱們傳遞 props
    console.log(props);      // {}
    console.log(this.props); // {}
  }
  // ...
}
複製代碼

這樣就確保 this.props 被設置在執行 constructor。

在 React 16.6 增長了context 在constructor 第二個參數,爲何 咱們不寫 super(props, context )? 實際上你能夠這樣寫,但實際上 context 用的比較少,因此沒有這樣傳。

最後,隨着 class fidlds propsal 這個tc39提案引入,上面的這些問題大部分都不會存在。沒有 constructor , 全部的參數都會自動傳遞過來,就像 state = { } 表達式這樣寫法,this.props 和 this.context 會自動被引用。

引用: overreacted.io/why-do-we-w…

相關文章
相關標籤/搜索