为什么我们需要在类组件的构造函数中绑定方法?

2025-06-08

为什么我们需要在类组件的构造函数中绑定方法?

如果我们回到hooks还未诞生的年代,在创建 React 类组件时我们必然会遇到这样的代码。

class MyClassComponent extends React.Component {
  constructor(props) {
    super(props);

    // Assuming that you need to pass this as a prop to one of a child component
    this.someMethod = this.someMethod.bind(this); // But why? 🤔
  }
 ... 
}

这是因为每当我们需要在类组件中将函数作为 props 传递给子组件时,我们都必须执行以下操作之一:

你有没有想过,为什么事情必须这样发展?为什么我们还要做这些额外的工作?

在本文中,我将首先尝试解释构造函数内部的绑定。掌握这些知识后,我们将尝试解释为什么箭头函数不遵循相同的规则。

我们需要知道的是,构造函数中的绑定与 React 无关。它纯粹与 JavaScript 如何实现this有关。让我们看下面的代码:

var x = 10;
let foo = {
  x: 90,
  getX: function() {
    return this.x;
  }
};

foo.getX(); // prints 90

let xGetter = foo.getX;

xGetter(); // prints 10;

当我们将x初始化到全局作用域时,它就成为了window对象的属性(假设它是浏览器环境,而不是严格模式)。我们可以断言:

window.x === 10; // true

this始终指向调用该方法的对象。因此,在foo.getX()的例子中,this指向foo对象并返回值 90。而在xGetter()的例子中,this指向window对象并返回值 10。

要检索foo.x的值,我们可以通过使用Function.prototype.bind将this的值绑定foo对象来创建一个新函数

let getFooX = foo.getX.bind(foo);
getFooX(); // prints 90

有了这些知识,让我们尝试了解将函数 prop 传递到子组件时会发生什么。

在下面的代码示例中,我们创建了一个虚拟组件来模拟 React 组件的思维模型。在render函数内部,我们返回一个普通的 JS 对象,该对象具有一个名为'onClick'的功能性 prop 。

React 元素只是一个不可变的描述对象,具有
两个字段:type: (string | ReactClass) 和 props: Object

class Component {
  constructor() {
    this.state = 10;
    this.setState = function() {
      console.log('state');
    };
  }

  handleClick() {
    this.setState();
  }

  render() {
    // return a child component.
    return {
      type: 'button',
      props: {
        // pass functional props
        onClick: this.handleClick,
        children: 'Click Me'
      }
    };
  }
}

// 1. creating a component instance
const componentInstance = new Component();

// 2. calling a render method on the instance
// ( In reality, React does the same thing for your class components)
const element = componentInstance.render();

// 3. calling the onClick function, which was passed as a  prop,
// will throw a 'TypeError: this.setState is not a function'.
element.props.onClick();

现在这个 TypeError 很明显了,因为 this 指向的props对象并不知道 setState 函数的存在。setState函数只是 componentInstance 的一个属性

因此,为了解决这个问题,我们必须在构造函数中绑定 handleClick 函数:

// inside constructor function
constructor() {
  // bind returns a new function
  this.handleClick = this.handleClick.bind(this);
}

...

// calling onClick will print 'state' this time.
element.props.onClick();

现在, this的值将始终指向具有setState作为其属性之一的componentInstance,并且不会抛出任何 TypeError。


好了,这就是我们第一个问题的答案。目前进展顺利。接下来,我们将努力找到第二个问题的答案。

查看下面的代码:

let bar = { someMethod: function() { return this; } };

bar.someMethod(); // print {someMethod: f}

let foo = { someMethod: () => this};

foo.someMethod(); // prints global 'window' object

箭头函数没有自己的 this 。它始终由创建箭头函数时其周围的作用域决定。

箭头函数没有自己的this 。

当我们在类内部使用箭头函数(使用属性初始化器功能)时,它会成为实例的方法属性。由于this始终由外部作用域决定,因此它将指向该类的实例。让我们看看实际效果:

class Component {
  constructor() {
    this.state = 10;
    this.setState = function() {
      console.log('state');
    };
  }

  // using fat arrow function; no binding require inside constructor
  handleClick = () => {
    // this will now point to the instance of Component class which knows about the setState method property
    this.setState();
  };

  render() {
    // return a child component.
    return {
      type: 'button',
      props: {
        // pass functional props
        onClick: this.handleClick,
        children: 'Click Me'
      }
    };
  }
}
// 1. creating a component instance
const componenttInstance = new Component();

//  2. calling a render method on the instance ( In reality, React does the same thing for your class components)

const element = componenttInstance.render();

// 3. calling onClick will now print 'state' to the console.
element.props.onClick();

希望您喜欢这篇文章,现在能够自信地回答这个问题。我强烈建议您阅读Axel Rauschmayer 博士的这篇文章,其中详细介绍了它的工作原理。this

感谢您的阅读,如果您喜欢这篇文章,那么几句❤️肯定会让我微笑😍。

链接地址:https://dev.to/aman_singh/why-do-we-need-to-bind-methods-inside-our-class-component-s-constructor-45bn
PREV
使用 OpenCV 和 Python 进行手指检测和跟踪
NEXT
延迟加载 React 组件——并非高深莫测