this 是 JavaScript 语言的一个关键字。
构造函数中的 this
在上一部分,我们使用了方法中的 this 来访问该方法所属的 对象。让我们再来看一个例子:
function Cat(name) { |
在上面的 Cat() 构造函数中,sayName 所指向的函数引用了 this.name。之前,我们已经看到过在方法中使用 this,但在这里,this 是指什么呢?
事实证明,当使用 new 运算符来调用构造函数时,this 会被设置为新创建的对象!让我们来看看新的 bailey 对象是什么样的:
{ |
在以上代码段中,请注意 this 位于构造函数 外部。正如我们在上一篇文章中所看到的,当你说 this 时,你其实是在说“这个对象”或“当前对象”。因此,sayName() 方法可以使用 this 来访问该对象的 name 属性!这使得以下方法调用成为可能:
bailey.sayName(); |
this 什么时候会被赋值?
一个常见的误解是,this 指向定义它的对象。事实并非如此!直到某个对象调用使用 this 的方法,this 才会被赋值。换句话说,赋给 this 的值取决于 调用定义 this 的方法的对象。让我们来看一个例子:
const dog = { |
让我们继续调用 dog 的两个方法:
dog.bark(); |
我们知道,当我们调用 dog.bark() 或 dog.barkTwice() 时,变量 this 将被设置。由于 this 可以访问调用它的对象,因此 barkTwice 可以使用 this 来访问包含 bark 方法的 dog 对象。
但是,如果我们在 barkTwice 中使用 bark(),而不是 this.bark(),将会怎样?该函数会先在 barkTwice 的作用域内查找一个名为 bark 的局部变量。如果没有找到 bark,则会沿着作用域链继续查找。
综合来看:this.bark() 会告诉 barkTwice 查看 dog(调用该方法的对象)以查找 bark。
this 会被设置为什么?
到目前为止,我们已经在许多不同的上下文中看到了 this,比如在方法中,或被构造函数引用。现在,让我们把它们放在一起来看一下!
有四种方式可以调用函数,而每种方式都会不同地设置 this。
- 首先,使用 new 关键字来调用构造函数会将
this设置为一个新创建的对象。还记得吗,在我们之前创建Cat()的实例时,this 被设置为新的bailey对象。 - 另一方面,调用属于一个对象的函数(即_方法_)会将
this设置为该对象本身。回想一下前面的示例,dog对象的barkTwice方法能够访问dog本身的属性。 - 第三,单独调用一个函数(即简单地调用一个常规函数)将把
this设置为window。如果主机环境是浏览器,则它将是全局对象。
function funFunction() { |
- 第四种调用函数的方式可以让我们自己设置 this!现在不用在意这一点,我们将在下一部分进行深入探讨。
| Call Style | new |
method | function |
|---|---|---|---|
this |
{} | object itself | global object |
| Example | new Cat() | bailey.sayName() | introduce() |
如果使用
new运算符来调用构造函数,this的值将被设置为新创建的对象,如果在对象上调用方法,this将被设置为该对象本身,如果简单地调用一个函数,this将被设置为全局对象:window
小练习
请考虑以下构造函数
City:
function City(name, population) { |
当 const sanFrancisco = new City('San Francisco', 870000); 被执行时,this 的值是什么?
答案: 新创建的对象,被 sanFrancisco 引用
请考虑以下对象
building:
const building = { |
当 building.addFloor() 被执行时,this 的值是什么?
答案: building
当以下函数被调用时,this 的值是多少?
function myFunction() { |
答案: window
小结
函数、对象和 this 彼此相互关联。当使用 new 运算符来调用构造函数时,this 变量会被设置为新创建的对象。当在对象上调用方法时,this 会被设置为该对象本身。当在浏览器环境中调用函数时,this 会被设置为 window,也被称为全局对象。
除此之外,还有一组方式可以调用函数:使用 apply() 和使用 call()。这两种方式有许多相似之处,每一种方式都允许我们指定如何设置 this。接下来,我们会对它们进行详细分析!