本文翻译自 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]);
// 返回 21
bind
方法与 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
的方法