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

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

内容简介:我听说现在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


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

查看所有标签

猜你喜欢:

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

CSS3 For Web Designers

CSS3 For Web Designers

Dan Cederholm / Happy Cog / 2010-11 / $18

From advanced selectors to generated content to the triumphant return of web fonts, and from gradients, shadows, and rounded corners to full-blown animations, CSS3 is a universe of creative possibilit......一起来看看 《CSS3 For Web Designers》 这本书的介绍吧!

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

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

HEX CMYK 互转工具

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

HSV CMYK互换工具