我听说现在Hooks是新的热点。讽刺地是,我想描述类的相关事实作为这片博客的开始。那是怎么样的呢?

这些坑对于有效地使用React并不重要。但如果你想更深入地了解事物的工作原理,你可能会发现它们很有趣。

这是第一个。


我的生命中我写的 super(props)

在我的生命中我写的super(props)比我知道的多:

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

当然,类相关的提议让我们跳过了这个仪式:

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

2015年React 0.13增加了对纯类的支持时,就计划了这样的语法。定义constructor函数和调用super(props)一直是一种临时解决方案,直到类字段提供了一种符合人体工程学的替代方案。

但是让我们回到这个例子,只使用ES2015特性:

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

为何我们要调用super?我们可以不调用它吗?如果我们不得不调用它,不传props参数会发生什么呢?还存在其它的参数吗? 让我们一探究竟。

为何我们要调用 super?调用不当会发生什么呢?


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

重要的是,你不能使用this直到你调用父级的constructor后。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 forks!');}
}
复制代码

想象一下thissuper之前被调用是被允许的。一个月后,我们可能改变greetColleagues中包含在person中的信息:

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

但是我们忘记了super()在有机会设置this.name之前调用了this.greetemployees(),因此this.name都还没定义。正如你所看到的一样,很难思考像这样的代码。

为了避免这样的坑,JavaScript会迫使你在使用this之前先调用super. 让父级做它该做的事情!这个限制也适用于定义为类的React组件:

construtor(props) {super(props);// ✅ Okay to use `this` nowthis.state = { isOn: true };
}
复制代码

这里还存在另外一个问题:为什么要传递props?


你也许认为传递propssuper是必要的,这样React.Component构造函数就能初始化this.props了:

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

这与事实相去不远——确实,事实就是如此。

但是,即使你调用super没带props参数,你依然可以在render或者其它方法中获取到props。(如果你不信我,你可以自己试试!)

那到底是怎样工作的呢?事实表明 React也会在调用构造函数后立即在实例上初始化props:

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

因此即使你忘记了给super传递propsReact也会立即设置它们。这是有原因的。

当React添加了对类的支持时,它不仅仅只支持ES6中的类。目标是支持尽可能广泛的类抽象。目前还不清楚使用ClojureScript,CoffeeScript,ES6,Fable,Scala.js,TypeScript,或者其它方式定义组件会有多成功。因此,React故意不明确是否需要调用super()——即使ES6的类需要。

所以这就意味着你可以使用super()代替super(props)了吗?

可能不是因为它仍然令人困惑。 当然,React会在你运行了constructor之后为this.props赋值。但是在super调用和构造函数结束之间,this.props仍然是未定义的:

// Inside React
class Component {construtor(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 }// ...
}
复制代码

如果在从构造函数调用的某个方法中发生这种情况,调试可能会更加困难。这就是为什么我总是建议大家传super(props),尽管它不是必需的:

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

保证在constructor存在之前this.props就被设置了。


还有最后一点React用户可能会感到好奇的。

你可能注意到在类中使用Context API时(包括旧的contextTypes和在React16.6中添加的现代contextType API),context作为第二个参数被传给constructor

为什么我们不用super(props, context)代替呢?我们能够,只是上下文的使用频率较低,所以这个坑不会经常出现。

随着类字段的提议,这个坑基本上消失了。 如果没有显式构造函数,所有参数都将被自动传递下去。这就是允许像state ={}这样的表达式包含对this.props或者this.context的引用的原因。

使用Hooks,我们甚至不会使用到super或者this。但是那是下次的话题。

原文链接:overreacted.io/why-do-we-w… by Dan Abramov

转载于:https://juejin.im/post/5c0f7ca551882516be2f011e

【译】为何我们要写super(props)?相关推荐

  1. 【译】为什么要写super(props)

    译注: 原文地址 https://overreacted.io/why-do-we-write-super-props/ 正文 我听说Hooks是新的热点.好笑的是,我想通过描述一些关于class组件 ...

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

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

  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. 【译】用JavaScript写一个区块链

    原文:Writing a tiny blockchain in JavaScript 作者:Savjee.be 译者:JeLewine 几乎每个人都听说过像比特币和以太币这样的加密货币,但是只有极少数 ...

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

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

最新文章

  1. 深度学习Dropout技术分析
  2. Codeforces 486D D. Valid Sets
  3. Web Socket/Stomp——整合Spring Session【Header Token模式】解决方案
  4. Mangos源码分析(3):服务器结构探讨之简单的世界服实现
  5. P1433 吃奶酪(状压dp)
  6. 二叉搜索时与双向链表python_剑指Offer(二十六) 二叉搜索树和双向链表
  7. codeforces 133A-C语言解题报告
  8. travis-ci自动部署_如何使用Travis CI设置高级自动部署
  9. AR增强现实开发介绍
  10. QT初探(QT+VS2010)
  11. python处理地震sac数据_自己开发的一个SEED格式地震数据转换为SAC格式数据,并完成世界时整天波形合并的Python脚本...
  12. 录制软件obs的使用方法
  13. 行人重识别论文阅读12-Bi-directional Exponential Angular Triplet Loss for RGB-Infrared Person ReID
  14. 2021年海河英才计划天津落户天津最详细过程
  15. 股指跨期套利基础学习
  16. obj[key].obj['key'],obj.key的区别
  17. Android 触摸OnTouchListener没有响应问题解决
  18. 云服务器快速建网站_安装BT宝塔面板和wordpress
  19. js分割thymleaf的字符串
  20. JS事件—unload、beforeunload

热门文章

  1. SpringBoot中操作spring redis的工具类
  2. Redis的持久化机制-RDB方式和AOF方式
  3. 50本.NTE、C#相关技术书籍免费下载
  4. DevExpress的TreeList实现节点上添加自定义右键菜单并实现删除节点功能
  5. SpringCloud-服务注册与实现-Eureka创建服务注册中心(附源码下载)
  6. Winform中设置ZedGraph的曲线为散点图
  7. Linux上操作Docker守护态运行
  8. EasyUI中分页的简单使用
  9. 360极速浏览器进行打印时会带出网页地址问题
  10. 神策数据入选 Facebook 全球合作计划,助力出海客户拥抱全球化广告生态