JavaScript 中 this 关键字的指向规则详解

作者:异步漫步

时间:2026-10-22

浏览:466

本文深入解析 JavaScript 中 this 关键字的指向逻辑,涵盖全局作用域、对象方法调用、new 构造函数以及 call、apply、bind 等显式绑定方式。通过具体代码示例,帮助开发者理解不同执行环境下 this 的绑定规则,避免常见陷阱。

文章目录

JavaScript this 关键字概述

JavaScript 中的 this 关键字与 Java 等面向对象语言中的实现存在显著差异,而 bind()、call() 和 apply() 方法进一步增强了 this 绑定的灵活性。

出于可读性考虑,本文采用意译方式而非逐字直译。文章版权归原作者所有,翻译内容仅供学习参考。

若对 JavaScript 中的 this 理解不够深入,容易陷入意想不到的逻辑陷阱。本文总结了五条通用规则,用于判断 this 的具体指向。虽然这些规则未涵盖所有极端情况,但足以应对日常开发中的大部分场景。

this 的值通常由函数的执行环境决定,即取决于函数是如何被调用的。这意味着同一个函数在每次调用时,this 可能指向不同的对象。

全局作用域中的 this

全局对象 (Global Object)

打开 Chrome 浏览器开发者面板(Windows 系统按 Ctrl + Shift + J,Mac 系统按 Cmd + Option + J),并在控制台中输入以下代码:

console.log(this);

观察控制台输出结果。


// Window {}

输出结果为 window 对象。这是因为在全局作用域下,this 默认指向全局对象,在浏览器环境中即为 window 对象。为了更清晰地理解这一机制,我们来看另一个示例:

var myName = 'Brandon'; 你可以在控制台输入 myName 来访问其值:


myName
// 输出 'Brandon'

事实上,所有在全局作用域中定义的变量都会自动绑定到 window 对象。我们可以进行如下测试:


window.myName
// 输出 'Brandon'
window.myName === myName
// 输出 true

接下来,我们将 this 放入函数内部,观察其表现。


function test(){
 return this;
}
test();

你会发现 this 依然指向全局的 window 对象。这是因为 this 关键字并未处于某个声明对象的内部,因此默认指向全局 window 对象。这一特性对许多初学者来说可能难以理解,但读完本文后你会豁然开朗。 注意:如果在 strict 模式下运行上述代码,this 的值将为 undefined。

对象方法中的 this

声明的对象 (Declared Object)

当 this 关键字在声明的对象内部使用时,其值会被绑定到调用该函数的最近父对象。我们通过示例来说明这一机制:


var person = {
 first: 'John',
 last: 'Smith', 
 full: function() {
  console.log(this.first + ' ' + this.last);
 }
};
person.full();
// 输出 'John Smith'

在声明的对象 person 中的 full 函数内部使用了 this,因此调用 this 的 full 函数的最近父对象是 person,所以 this 指向 person。

为了更直观地展示 this 实际上指向 person 对象,你可以将以下代码复制到浏览器控制台中,打印出 this 的值。


var person = {
 first: 'John',
 last: 'Smith', 
 full: function() {
  console.log(this);
 }
};
person.full();
// 输出 Object {first: "John", last: "Smith", full: function}

接下来我们看一个更复杂的嵌套对象示例:


var person = {
 first: 'John',
 last: 'Smith',
 full: function() {
  console.log(this.first + ' ' + this.last);
 },
 personTwo: {
  first: 'Allison',
  last: 'Jones',
  full: function() {
   console.log(this.first + ' ' + this.last);
  }
 }
};

在此例中,this 分别指向哪里?我们将其打印出来验证:


person.full();
// 输出 'John Smith'
person.personTwo.full();
// 输出 'Allison Jones'

结果符合前文所述的规则:this 的值会被绑定到调用 this 的函数的最近父对象。

使用 new 关键字时的 this

new 关键字

当使用 new 关键字构建新对象时,this 会绑定到这个新创建的对象。我们来看一个示例:


function Car(make, model) {
 this.make = make;
 this.model = model;
};

根据第一条规则,你可能会推断 this 指向全局对象。但是,如果我们使用 new 关键字声明一个新变量,Car 函数中的 this 将绑定到一个新的空对象,并初始化 this.make 和 this.model 的值。


var myCar = new Car('Ford', 'Escape');
console.log(myCar);
// 输出 Car {make: "Ford", model: "Escape"}

显式绑定:call、apply 和 bind

call, bind, 和 apply

我们可以显式地在 call()、bind() 和 apply() 中设置 this 的绑定对象。这三个函数功能相似,但需要注意它们之间的细微区别。

<!-- call 可以接收任意个数的参数,其中第一个必须是一个 this 对象,其余依次是所有的参数。 -->

我们来看一个示例:


function add(c, d) {
 console.log(this.a + this.b + c + d);
}
add(3,4);
// 输出 NaN

add 函数输出 NaN,因为 this.a 和 this.b 未定义。

现在我们引入对象,并使用 call() 和 apply() 来调用:


function add(c, d) {
 console.log(this.a + this.b + c + d);
}
var ten = {a: 1, b: 2};
add.call(ten, 3, 4);
// 输出 10
add.apply(ten, [3,4]);
// 输出 10

当我们使用 add.call() 时,第一个参数是 this 需要绑定的对象,其余参数是 add 函数原本的参数。 因此,this.a 指向 ten.a,this.b 指向 ten.b。add.apply() 的情况类似,唯一的区别是第二个参数是一个数组,用于存储 add 函数的参数。

bind() 函数与 call() 类似,但 bind() 不会立即执行。bind() 会返回一个新函数,并将 this 绑定好。接下来我们通过示例来理解 bind() 的应用场景:


var small = {
 a: 1,
 go: function(b,c,d){
  console.log(this.a+b+c+d);
 }
}
var large = {
 a: 100
}

执行以下代码:


small.go(2, 3, 4);
// 输出 10

如果我们想使用 large.a 的值,而不是 small.a 呢?我们可以使用 call/apply:


small.go.call(large, 2, 3, 4);
// 输出 109

但是,如果我们现在还不知道这三个参数应该传入什么值,应该怎么办呢?我们可以使用 bind:

var bindTest = small.go.bind(large, 2);

如果我们将 bindTest 在控制台下打印出来,我们会看到:


console.log(bindTest);
// 输出 function (b,c,d){console.log(this.a+b+c+d);}

注意:该函数已经将 this 绑定到 large 对象,并且传入了第一个参数 b。因此,接下来我们只需要传入剩余的参数即可:


bindTest(3, 4);
// 输出 109

箭头函数与 this

箭头函数(=>)

由于篇幅较大,我们将专门撰写一篇博客来详细介绍。

总结

结论

读完本文后,你应该能够理解大多数情况下 this 指向的对象。 接下来我们来总结一下:

this 的值通常由当前函数的执行环境决定; 在全局作用域中,this 指向全局对象(window 对象); 当使用 new 关键字声明时,this 指向新建对象; 我们可以使用 call()、bind()、apply() 来设置 this; 箭头函数不会绑定 this。

原文: JavaScript: The Keyword ‘This' for Beginners

译者: Fundebug

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章