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

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

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

我听说现在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) {
    // :red_circle: Can’t use `this` yet
    super(props);
    // :white_check_mark: Now it’s okay though
    this.state = { isOn: true };
  }
  // ...
}
复制代码

有一个很好的理由可以解释为什么JavaScript会强制父构造函数在你访问 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 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);
    // :white_check_mark: Okay to use `this` now
    this.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(); // :grimacing: We forgot to pass props
    console.log(props);      // :white_check_mark: {}
    console.log(this.props); // :grimacing: undefined 
  }
  // ...
}
复制代码

如果在从构造函数调用的某个方法中发生这种情况,调试可能会更加困难。 这就是为什么我总是建议大家传 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: {}
    }
}
复制代码

保证在 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… byDan Abramov


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

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

.net之美

.net之美

张子阳 / 机械工业出版社 / 2014-1-1 / 79

本书是.NET 程序员进阶修炼的必读之作,由拥有多年开发经验的资深.NET 技术专家对C# 和.NET 中实用的、关键的和难以理解的知识点进行了深入解析,旨在帮助读者在尽可能短的时间内以 尽可能低的学习成本去掌握那些最应该被掌握的知识。书中的每个知识点都辅之以精心设计的案例,易 于理解,实践性强。 全书共17 章,分为两个部分:第一部分(1~5 章)主要讲解了C# 语言中的一些关键知识点,如......一起来看看 《.net之美》 这本书的介绍吧!

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

在线 XML 格式化压缩工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具