为什么我们要添加 super(props) ?

栏目: JavaScript · 发布时间: 5年前

内容简介:我听说Hooks 成了新的焦点。但是呢,我想通过这篇博客来介绍下class声明组件有趣的地方。意下如何?下面内容无法提高你的React使用技巧。但是,当你深入探究事物是如何运行时,将会发现它们所带来的喜悦之情。首先来看看第一个例子。

我听说Hooks 成了新的焦点。但是呢,我想通过这篇博客来介绍下class声明组件有趣的地方。意下如何?

下面内容无法提高你的React使用技巧。但是,当你深入探究事物是如何运行时,将会发现它们所带来的喜悦之情。

首先来看看第一个例子。

我写 super(props) 的次数比我想象中多得多:

class Checkbox extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isOn: true };
  }
  // ...
}
复制代码

当然, class fields proposal (JS提案)使我们跳过这个过程:

class Checkbox extends React.Component {
  state = { isOn: true };
  // ...
}
复制代码

这是在2015年,在React0.13版本时添加支持的类语法planned。在 class fields 这个更合理的替代方案出来之前,声明 constructor 和调用 super(props) 一直被做为一种临时的解决方案。

但在此之前,让我们回到只使用ES2015的例子:

class Checkbox extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isOn: true };
  }
  // ...
}
复制代码

为什么要调用 super ?我们可以 调用它吗?如果我们必须调用它,那调用时不传 props 会怎么样呢?会有更多的参数吗?来一起找找答案。

JavaScript中, super 是父类constructor的引用。(我们例子中,它指向 React.Component

很重要的一点,你是无法在父类的constructor调用之前在constructor中使用 this 的,JavaScript不允许你这样做:

class Checkbox extends React.Component {
  constructor(props) {
    // :red_circle: Can’t use `this` yet
    super(props);
    // :white_check_mark: Now it’s okay though
    this.state = { isOn: true };
  }
  // ...
}
复制代码

JavaScript 会强制父类constructor在你碰 this 前被执行是有原因的。想想类的层次结构:

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

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

假设在 super 之前允许调用 this 。一个月之后,我们可能在 greetColleagues 的消息中加入了 name 属性:

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

然而我们忘记了声明 this.namesuper 方法被调用之前,已经调用了 this.greetColleagues() 。以至于 this.name 变成了 undefined 的状态!如你所见,代码会因此变得难以揣测。

为了避免这种陷阱, JavaScript 强制要求, 如果想在constructor里使用 this ,就 必须 先调用 super 。让父类做好它的事先!这个限制也适用于定义别的React组件:

constructor(props) {
    super(props);
    // :white_check_mark: Okay to use `this` now
    this.state = { isOn: true };
  }
复制代码

还有另外一个问题,为什么要传 props

你可能会认为,之所以 super 里要传 props ,是为了在 React.Component 的constructor里初始化 this.props

// Inside React
class Component {
  constructor(props) {
    this.props = props;
    // ...
  }
}
复制代码

实际上也差不多是这个原因,这是 确切原因

但在一些时候,即使在调用 super 时不传 props 参数,你仍然可以在 render 和其他方法中获取到 this.props 。(如果你不信,自己试下咯!)

这是如何实现的呢?原因是,在你的组件实例化后,会赋值 props 属性给实例对象。

// Inside React
  const instance = new YourComponent(props);
  instance.props = props;
复制代码

所以即使忘记传 propssuper ,React仍然会在之后设置它们,这是有原因的。

当React添加对类的支持时,它不仅仅增加了对ES6的支持,目标是尽可能支持广泛的类抽象化。当时我们还不清楚如ClojureScript, CoffeeScript, ES6, Fable, Scala.js, TypeScript或其他解决方案怎样算成功地定义组件,所以React也就不关心是否需要调用 super() 了——即便是ES6。

所以说是可以只用 super() 来替代 super(props) 吗?

最好不要。因为这样仍然有问题。没错,React可以在你的constructor运行后给 this.props 赋值。但 this.props 在调用 super 和constructor结束前仍然是 undefined

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

// Inside your code
class Button extends React.Component {
  constructor(props) {
    super(); // :grimacing: We forgot to pass props
    console.log(props);      // :white_check_mark: {}
    console.log(this.props); // :grimacing: undefined 
  }
  // ...
}
复制代码

如果在constructor中有某些方法存在这种情况,它将会变得难以调试。 这也是为什么我一直建议添加 super(props) ,即使没有需要:

class Button extends React.Component {
  constructor(props) {
    super(props); // :white_check_mark: We passed props
    console.log(props);      // :white_check_mark: {}
    console.log(this.props); // :white_check_mark: {}
  }
  // ...
}
复制代码

这确保了 this.props 在constructor完成之前就被赋值。

最后还有一点是长期以来React使用者可能会感到好奇的。

你可能会注意到当你在类中使用 Context API(无论是过去的 contextTypes 或是后来在React 16.6中添加的 contextType API, context 都会做为constructor的第二个参数用来传递)。

所以我们为什么不用 super(props, context) 来替代呢?其实我们可以,但 context 的使用频率较低,所以遇到的坑没有那么多。

当有了class fields proposal,大部分的坑都会消失。在没有标明constructor的情况下,全部参数会被自动传入。这样就允许像 state = {} 的表达式,如果有需要 this.props 或者 this.context 将同样适用。

Hooks中,我们甚至不需要 super 或者 this 。但这要改天再说。

翻译原文 Why Do We Write super(props)?


以上所述就是小编给大家介绍的《为什么我们要添加 super(props) ?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

JavaScript语言精粹

JavaScript语言精粹

Douglas Crockford / 赵泽欣、鄢学鹍 / 电子工业出版社 / 2009-4 / 35.00元

本书通过对JavaScript语言的分析,甄别出好的和坏的特性,从而提取出相对这门语言的整体而言具有更好的可靠性、可读性和可维护性的JavaScript的子集,以便你能用它创建真正可扩展的和高效的代码。 雅虎资深JavaScript架构师Douglas Crockford倾力之作。 向读者介绍如何运用JavaScript创建真正可扩展的和高效的代码。一起来看看 《JavaScript语言精粹》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具