本文翻译自 Trey 的这篇文章,并进行了略微修改。
如果你刚接触 React,你可能和我一样会被关键字 this 的使用搞糊涂。本文介绍了 JavaScript 以及 React 中 this 关键字的含义,以及更重要地,我们为什么时刻都在使用它。
this 关键字
根据使用的上下文不同,this 关键字通常会引用一个 JavaScript 元素。让我们举几个例子来说明这一点。
全局的 this 作用域
最直观的作用域就是在你浏览器中的全局作用域,如果你在浏览器中打开控制台,并输入以下内容:
this……浏览器就会返回位于全局的 Window 对象:
Window {frames: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, …}你在 Window 对象中执行的任何指令,均等价于你在全局作用域中使用 this 关键字来执行:
this.alert('嘿!')
// 等价于
Window.alert('嘿!')
this.location = 'https://dgideas.net'
// 等价于
Window.location = 'https://dgideas.net'函数中的 this 作用域
从这里开始事情有点复杂了,你最好首先了解作用域(Scope)的具体含义。
在 JavaScript 的函数中,this 的值由函数的调用方式决定。调用(Call)、应用(Apply)以及绑定(Bind)等方法能够显式地设定函数中 this 的值。然而,如果没有显式地设置 this,那么 this 将默认为全局上下文:
const thisFunction = function () {
    return this;
}
// 在浏览器中调用 thisFunction() 将返回 Window 对象在使用严格模式(Strict Mode)时,函数中的 this 将引用它的显式值,如果 this 没有被显式设置,那么 this 的值将会是未定义的:
const strictFunction = function() {
    'use strict';
    return this;
}
// 在浏览器中调用 strictFunction() 将返回 undefined,因为这不是通过调用、应用或绑定来明确设置的通过调用、应用、绑定和箭头函数明确设置 this
那么,我们如何在函数上显式地设置 this 呢?调用、应用和绑定方法为我们做了这些工作。
函数的 call 方法接受 this 将引用的对象,以及函数中定义的其他参数。而 apply 方法接受  this 将引用的对象,以及一个包含定义函数时引用的参数的数组:
const object = {
    a: 5,
    b: 7
}
const thisFunction = function(c, d) {
    return this.a + this.b + c + d;
}
thisFunction.call(object, 12, 4);
// 返回 28
thisFunction.apply(object, [3, 6]);
// 返回 21bind 方法与 call 方法或者 apply 方法有显著不同,它将 this 要指代的对象附加在一个函数上。这样,每当这个函数被调用,this 就指向了预先绑定的对象上:
const object = {a: 2, b: 3, c: 6};
const thisFunction = function() {
    return this.a + this.b + this.c;
}
const bindFunction = thisFunction.bind(object);
bindFunction(); // 返回 11对象上下文
特别地,当我们在一个对象中使用 this 时,它指向的是对象本身。这使得在对象的方法中很容易引用对象的值:
const object = {
    a: 2,
    b: 3,
    thisFunction: function() {
       return this.a + this.b;
    }
};
object.thisFunction() // 返回 5这对 React 意味着什么
在 React 的组件(component)类中,我们定义的方法能够引用类的属性,如 props 和 state。而为了让我们的方法能够访问 this.state 和 this.props,我们需要将React组件的 this 上下文绑定到这些方法。
import React, {Component} from ‘react’;
class App extends Component {
    constructor(props) {
        super(props);
        this.clickFunction = this.clickFunction.bind(this);
    }
    clickFunction() {
        console.log(this.props.value);
    }
    render() {
        return(
          <div onClick={this.clickFunction}>Click Me!</div>
        );
    }
}将 this 绑定到类的方法中能够让我们通过组件中形如 this.props 以及 this.state 的方法访问 props 与 state。
箭头函数
我们注意到,将 this 绑定到类方法中可以构建出许多不同种的样板。自 ES6 中引入的箭头函数是一种已经绑定了当前 this 上下文的函数。由于这个有趣的特性,我们可以将公共类字段自动地绑定在我们的方法中:
const myFunction = () => {
 return this.props.a + this.props.b;
}
// 上述代码等价于...
const myFunction = function() {
  return this.props.a + this.props.b;
}.bind(this);通过将箭头函数和公共类字段进行结合,我们可以得到构建 React 组件的一种简洁、声明式的方式。
总结
- 除非使用箭头函数,否则我们需要显式地为函数上下文绑定 this对象
- call、- apply与- bind是三种不同的显式设置- this的方法