当前位置: 首页 > 面试题库 >

为什么我必须对React组件类中定义的方法进行.bind(this),而在常规ES6类中却不必

祁星阑
2023-03-14
问题内容

令我感到困惑的是为什么当我定义一个反应组件类时,除非在类中使用箭头函数定义或使用该方法定义该方法,否则该类中定义的方法this中未定义对象中包含的值(this生命周期方法中可用).bind(this)。以下代码this.state将在renderElements函数中未定义,因为我没有使用箭头函数定义它并且未使用.bind(this)

class MyComponent extends React.Component {
    constructor() {
        super();
        this.state = { elements: 5 }
    }

    renderElements() {
        const output = [];

        // In the following this.state.elements will be undefined
        // because I have not used  .bind(this) on this method in the constructor
        // example: this.renderElements = this.renderElements.bind(this)
        for(let i = 0; i < this.state.elements; i ++){
            output.push(<div key={i} />);
        }

        return output;
    }

    // .this is defined inside of the lifecycle methods and 
    // therefore do not need call .bind(this) on the render method.
    render() {
        return (
            <div onClick={this.renderElements}></div>
        );
    }
}

然后在下面的例子中,我不需要使用.bind(this)或箭头功能,this可作为预期speak功能

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

    speak() {
        console.log(this.name + ' makes a noise.');
    }
    }

    class Dog extends Animal {
    speak() {
        console.log(this.name + ' barks.');
    }
}

var d = new Dog('Mitzie');
d.speak();

http://jsbin.com/cadoduxuye/edit?js,控制台

为了澄清,我的问题分为两部分。一)为什么在第二个代码示例中我不需要调用.bind(this)speak函数,但是我在React组件中对该renderElements函数进行调用,二)为什么生命周期方法(render,componentDidMount等)已经可以访问该类?this对象,但renderElements不是。

在React文档中,它表示以下内容

[反应组件类]方法遵循与常规ES6类相同的语义,这意味着它们不会自动将其绑定到实例。

但是显然,它们确实可以做到,正如我发布的第二个代码示例所示。

更新资料

前两个注释中的两个链接都显示了一个不使用.bind(this)类方法的React类的工作示例,并且工作正常。但是仍然在文档中明确指出您需要绑定方法或使用箭头功能。在使用gulp和babel的项目中,我可以复制。难道浏览器已经更新了东西?

更新2

我的初始代码示例this.renderElements()直接在render函数中调用了。无需绑定功能或使用箭头功能定义它即可按预期工作。当我将函数用作onClick处理程序时,就会发生此问题。

更新3

当我将函数用作onClick处理程序时,就会发生此问题。

实际上,这根本不是问题。this更改的上下文传递给onClick处理程序时,这就是JS的工作方式。


问题答案:

组件中的事件处理程序不会像其他方法(生命周期方法…)那样自动绑定到组件实例

class MyComponent extends React.Component {
   render(){
      return (
         <div onClick={this.renderElements}>
             {this.renderElements()} <-- `this` is still in side the MyComponent context
         </div>
      )
   }
}
//under the hood

var instance = new MyComponent();
var element = instance.render();
//click on div
element.onClick() <-- `this` inside renderElements refers to the window object now

查看此示例以了解this更多信息:

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

    speak() {
        console.log(this.name + ' makes a noise.');
    }  
}

class Dog extends Animal {
    run(){
       console.log(this.name + ' runs');
    }
    speak() {
        console.log(this.name + ' barks.');
        this.run(); <-- `this` is still in the Dog context
        return {onRun : this.run};
    }
}

var d = new Dog('Mitzie');
var myDog = d.speak();
myDog.onRun() <-- `this` is now in the global context which is the `window` object

您可以查看本文以获取更多信息。



 类似资料:
  • 问题内容: 结合使用带有ReactJS的ES5开发,可以将组件描述如下: 在此的示例引用对象本身,这是预期的自然行为。 题 我的问题是: 如何使用ES6创建组件? 知道在JavaScript中使用new运算符时会引用实例化对象本身,因此有人可以告诉我使用bind的真正目的是什么?这和React的内部机制有关吗? 问题答案: 只是核心javascript。这是绑定事件的工作方式。这不是一个React

  • 出于某种原因,我在es6课上给“这个”取了个奇怪的值... null null 为什么clickers的click方法中的“this”指的是dom节点而不是...本身? 更重要的是,如果我不能使用“this”来做的话,我如何从它的click方法中引用clickers的count属性?

  • 问题内容: 我有一个javascript类,每个方法都返回一个Promise。我想知道为什么在和中未定义。有没有更正确的方法来编写此代码? 我可以使用以下方法解决此问题: 但是不能完全确定为什么有必要。正在消灭? 问题答案: 始终是调用方法的对象。但是,将方法传递给时,您不会调用它!该方法将存储在某个地方,稍后再从那里调用。如果要保存,则必须这样做: 或者,如果您必须在ES6 之前的版本中进行操作

  • 问题内容: 我希望这个问题不会太笼统。我知道,要在您上进行绘制,您需要重写该方法,并将所有绘制代码​​放入该方法中。我的问题是为什么!为什么Java似乎不允许/提供使用诸如或方法的绘图?在delphi中,一切都变得如此简单。一定有一个原因我无法弄清楚。 问题答案: 那是因为这就是它的工作方式。它是以此方式设计的。但是我想你的问题是关于“为什么” 请记住,Swing大约在15年前问世。批评之一是该A

  • 问题内容: 当我想在当前范围内引用该方法时,我仍然需要指定类名(对于静态方法)或在 运算符之前。例如,我需要写: 对于来说,这并不是什么大问题,但是对于静态方法而言,有时显得有些拥挤,因为类名可能会很长。如果编译器允许我直接编写代码,那就太好了: 但是Java-8编译器不允许这样做。对我来说,如果用与普通方法调用相同的方式解析类/对象名称,那似乎是非常一致的。这也将支持方法引用的静态导入,这在某些

  • 我正在为一个班级作业制作一个石头剪刀游戏,我正在尝试编写一个方法,根据用户获胜、计算机获胜还是平局,返回整数1、2或3。我们不能简单地返回信息“你赢了!”或者“你输了!”或“平局!”在该方法中,我们必须返回整数。然而,当我这样键入代码时,Eclipse中会出现一个编译器错误警告,告诉我“此方法必须返回int类型的结果。”这不是我在这里要做的吗?帮助谢谢