译注:
原文地址 https://overreacted.io/why-do-we-write-super-props/

正文

我听说Hooks是新的热点。好笑的是,我想通过描述一些关于class组件的事实来作为第一篇博客。这个想法怎么样!
这些陷阱对于有效的使用React并不重要。但是如果你喜欢深入挖掘运行机制,就会发现这些东西的又去之处。
下面介绍第一个。
我写过很多次 super(props) 但很多情况下,我并不了解为什么要写它。

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

当然,class fields 提案让我们可以跳过这步操作。

class Checkbox extends React.Component {state = { isOn: true };// ...
}

之前计划的一种支持plain class的语法(注:即类变量),已经在2015年,React0.13版中加入。在class fields完整确定之前,定义 constructor 和调用 super(props) 被当做一种临时方案。
但是,让我们回到只使用ES2015的例子里:

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

为什么要调用 super? 能不能不用它?如果不得不用它,在调用它时,发生了什么?还有其他的参数吗?


在JavaScript里,super指向父类构造器。(在我们的例子里, 他指向React.Component实现类)。
重点在于,如果调用了父类构造器,在调用super之前,无法使用this关键字。JavaScript不允许这么干。

class Checkbox extends React.Component {constructor(props) {// ? Can’t use `this` yetsuper(props);// ✅ Now it’s okay thoughthis.state = { isOn: true };}// ...
}

为什么JavaScript强制在调用this之前执行父类构造器?这里有一个好的解释。考虑一个类的层级结构:

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

想象一下如果在super之前使用this是允许的。一个月之后,我们可能修改greetColleagues来动态加载信息中的姓名。

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

但是我们忘记了this.greetColleagues()是在super()之前调用,它已经和this.name建立了联系。而this.name甚至还没有定义。你能发现,像这样的代码,真的很难理解。
为了避免这样的陷阱, 如果在构造器中调用this,JavaScript强制要求super要在this之前书写,让父类做它们应该做的事。这条限制也被应用到了React组件类定义中:

constructor(props) {super(props);// ✅ Okay to use `this` nowthis.state = { isOn: true };
}

这样就留给我们另一个问题: 为什么要传递props


你也许觉得对于React.Component构造器初始化this.props而言,通过super传递props非常重要。

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

这和真相相去甚远。事实上,这才是它做了什么。
但不知道为啥,即使你不传入props,直接调用super(),还是可以在render和其他方法里访问到this.props(如果你不相信我,自己试一下)。
这是怎么个情况?它实际上证实了React也会在调用constructor之后,立刻合并props

// Inside React
const instance = new YourComponent(props);
instance.props = props;

所以即使你忘记把props传递给super(),React也会及时设置上去的。下面是原因之一:

当React支持类方法声明组件时,并不是单单支持了ES6类语法。它的目标是支持所有抽象类范围内的声明方法。JavaScript有很多变种,如ClojureScript, CoffeeScript, ES6, Fable, Scala.js, TypeScript,或者是其他方式,并不是很好比较到底哪种方式去定义一个组件更合适。所以React故意固执得要求super(),虽然ES6 class是这样。
这下明白为什么能只写super()而不用写super(props)了吗?
也许还不明白,没关系,这个东西太令人困惑了。当然,React将会在构造器执行完毕后去合并this.props。但是在super和构造器结尾之间,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 propsconsole.log(props);      // ✅ {}console.log(this.props); // ? undefined }// ...
}

如果一些方法在构造器中调用,这样会给debug造成很大的挑战。这也是为什么我推荐传递super(props),虽然它不是必须的。

class Button extends React.Component {constructor(props) {super(props); // ✅ We passed propsconsole.log(props);      // ✅ {}console.log(this.props); // ✅ {}}// ...
}

这样确保了this.props在构造器存在前就已经被设置。


还有一点,React长期使用者可能会好奇。
你也许注意到了Context API传递了第二个参数给构造器。(不论是古老的contextTypes还是现在16.6新加的ContextAPI)。
为什么要写super(props, context)来代替super(props)?当然也行,但是context很少使用,所以这个陷阱不常出现。
在class fields提案通过之后,这些陷阱都没得差不多了。没有一个明确的constructor,所有的参数都会自动传递。这也是为什么一个表达式类似state={}可以包含this.propsthis.context引用。
通过使用Hooks,就不需要superthis了。但那是另一个主题了。

转载于:https://www.cnblogs.com/liuyongjia/p/10140071.html

【译】为什么要写super(props)相关推荐

  1. super()和super(props)的区别以及为什么要写super(props)

    一般,我们在写自定义类组件的时候会写上构造函数如下: class Checkbox extends React.Component {constructor(props) {super(props); ...

  2. 【译】为何我们要写super(props)?

    我听说现在Hooks是新的热点.讽刺地是,我想描述类的相关事实作为这片博客的开始.那是怎么样的呢? 这些坑对于有效地使用React并不重要.但如果你想更深入地了解事物的工作原理,你可能会发现它们很有趣 ...

  3. React构造函数中为什么要写 super(props)

    为什么 super() 要放在构造函数 contructor 最上面执行 ? ES6 语法中,super 指代父类的构造函数,React 里面就是指代 React.Component 的构造函数. 在 ...

  4. [react] super()和super(props)有什么区别?

    [react] super()和super(props)有什么区别? react 中的class 是基于es6的规范实现的, 继承是使用extends关键字实现继承的,子类必须在constructor ...

  5. 面试官:super()和super(props)有什么区别?

    一.ES6类 在ES6中,通过extends关键字实现类的继承,方式如下: class sup {constructor(name) {this.name = name}printName() {co ...

  6. 如何理解react中的super(),super(props)

    用es6的class(类)的方法创建组件: 子类继承父类的属性:需要使用super()继续父类的属性,同时创建this(子类本身没有this); 如果像上图一样需要定义props的属性 this.pr ...

  7. [react] 在构造函数中调用super(props)的目的是什么?

    [react] 在构造函数中调用super(props)的目的是什么? 这是ES6的语法.class组件继承自React.Component,super(props)之后,有以下几个作用: 初始化pr ...

  8. 如何从数据库中筛选出达成指定里程碑节点的项目_【译】如何写出一份优秀的软件设计文档...

    作为一名软件工程师,我花了很多时间阅读和编写设计文档.在完成了数百篇这些文档之后,我亲眼目睹了优秀设计文档与项目最终成功之间的强烈关联. 本文试图描述什么使设计文档变得更好. 本文分为4个部分: 为什 ...

  9. 为什么通常在类的init函数下一行写super().__init__()?==>就是执行父类的构造函数,使得我们能够调用父类的属性

    我们通常看到 那么这一行代码的意义是什么呢? 实例: class Root(object):def __init__(self):self.x = '这是属性'def fun(self):print( ...

最新文章

  1. 耗时3天,上亿数据如何做到秒级查询?
  2. javascript的变量
  3. UML实践详细经典教程
  4. 使用Spring Boot来加速Java web项目的开发
  5. mysql视图管理和存储过程
  6. C语言转义字符介绍和示例
  7. 波卡生态项目Polkalokr将在Polkastarter进行IDO
  8. python pip下载安装一半退出_【Python】pip安装numpy安装到一半失败解决办法
  9. 向量的方向余弦公式_方向余弦怎么求
  10. 成本更低、更优观看体验——自研S265编解码器解析
  11. 模拟卷Leetcode【普通】729. 我的日程安排表 I
  12. PostgreSQL数据库WAL——RM_HEAP_ID日志记录动作
  13. MicroPython ESP32 ADC(模拟量转数字量)示例
  14. 6.后台验证码-session作用域
  15. 常成员函数和静态成员函数
  16. nodejs ---- 起步
  17. html json是什么文件,JSON是什么?
  18. 遥信、遥测、遥脉和数字量的区别
  19. 论文参考文献格式标准
  20. js 拖拽元素 鼠标速度过快问题

热门文章

  1. 简单图文配置golang+vscode【win10/centos7+golang helloworld+解决install failed等情况】
  2. deepin初试与file browser使用小结
  3. Ubuntu 16.04 安装 PyInstaller
  4. 2022-2028年中国香薰行业市场研究及前瞻分析报告
  5. Go 学习笔记(63)— Go 中的 for ... range 对切片和数组的差异
  6. 愿疫情早日过去,向那些在疫情战斗中牺牲的战士致敬
  7. Flask学习之路(一)--初识flask
  8. 残差复合正态分布的重要性
  9. tensorflow 学习笔记-- tf.reduce_max、tf.sequence_mask
  10. WebRTC框架中的硬件加速