浅谈 JavaScript / TS 中的 this


Photo by David Marcu on Unsplash

在 JavaScript 中 this 所指向的对象与运行时上下文进行绑定,这就会导致在不同场景下,函数最终运行结果可能不尽相同。

非对象/实例化环境

非对象/实例化环境指的是普通的函数( 没有通过原型方法构造对象的函数 )环境以及直接在全局下使用 this(如直接在页面的上输出 this)。

在非对象/实例化环境下,this 在不同开发环境指向的是不同的默认对象。在 Node.js 环境下,默认指向的是 module.exports,在浏览器环境,默认指向 window。

对象/实例化环境

在对象/实例化环境场景下,要分清 this 的作用域,只需看对象是什么。

普通对象


假如 this 在一个普通字典对象中,且通过该对象的属性或者方法直接访问这个 this,那么此时它指向的就是对象本身。 在下面这个例子中,当我们通过调用 Person.getName() 来获取对象本身的属性时,this 指向 Person 对象。

函数对象

假设我们通过 function 的方式,利用原型链构造一个类,然后通过对象的实例方法来调用 this。那么,此时 this 指向的就是该类的一个实例。

复用原型方法

承接上面的例子,若直接调用原型上的方法,this 指向的 Person.prototype 这个原型对象。所以若其他对象想将此方法复用在自身,就必须使用 bind、call、apply 将其绑定到自身对象上。

令人迷惑的现象

有了以上知识,我们就可以知道一个 this 到底指向的是哪个对象。甚至可以解读下面这个令人迷惑的例子中的 this 的指向。

这里 cardPicker 是由对象方法返回的函数,但它仍是一个普通函数。故函数中的 this 被置为默认对象——module.exports 或 window。由于默认对象中并没有card 和 suits 属性,故一旦 cardPicker 被用户调用,就会有 undefined 报错。

最后

关于 this,Typescript 对箭头函数中 this 指向的对象进行了合理化的改造——箭头函数中的 this 始终指向的是拥有此方法的对象本身。这样就不会产生上一节提到的那些违背“直觉”的现象。

参考链接

Meaning of “this” in node.js modules and functions

How does the “this” keyword work?

JavaScript 的 this 原理

What is “this”?

Object methods, “this”

发表评论

电子邮件地址不会被公开。 必填项已用*标注