深入理解JavaScript中this的绑定机制与规则
本文深入解析JavaScript中this关键字的绑定机制,澄清指向函数自身或词法作用域的常见误解。详细阐述默认绑定、隐式绑定、显式绑定(call/apply/bind)及new绑定的四种核心规则,并结合代码示例说明不同调用方式下this的具体指向,帮助开发者掌握this的动态绑定特性。
this关键字的常见误解
在JavaScript语言中,闭包、this关键字以及原型链是三个最易让人困惑的核心概念。尽管利用词法作用域等机制可以规避this带来的诸多陷阱,但为了深入理解语言本质并提升编程能力,我们需要打破舒适区,彻底厘清其工作原理。
一、常见对this关键字的误解
1、认为this指向函数自身
2、认为this指向函数的词法作用域
我们可以通过以下代码片段进行验证:
function test() {
test.a = 1;
this.a = 2;
console.log(test.a);
console.log(this.a);
console.log(test.a === this.a);
}
test();
console.dir(test);
在上述代码中,我们在函数test内部将test.a赋值为1,同时将this.a赋值为2。如果假设this指向函数自身,那么test.a与this.a应当相等,且值均为2。
接下来观察这段代码的实际运行结果:


从结果可以看出,scopes变量指向全局作用域window,此时this也指向window。尽管函数本身在JavaScript中也是对象,但this并不指向函数本身。
必须明确一点:this是在运行时进行绑定的,而非编写时确定。其上下文完全取决于函数调用时的具体条件。this的绑定与函数声明的位置无关,仅由函数的调用方式决定。
既然this是运行时绑定,我们能否通过强制绑定方法(如call、apply、bind)改变当前this的指向,使其不指向window而指向方法test本身?答案是肯定的,修改后的代码如下:
function test() {
test.a = 1;
this.a = 2;
console.log(test.a);
console.log(this.a);
console.log(test.a === this.a);
}
test.call(test);
console.dir(test);
运行结果如下:


接下来探讨this是否指向函数的词法作用域,以下有一段具有代表性的代码:
function parent() {
var a = 2;
function child() {
console.log(this.a)
}
child();
}
parent();
若假设this指向函数的词法作用域,则child方法中的this.a应当存在。但实际执行结果如下:

实际上,在JavaScript内部,作用域确实类似于对象,其可见标识符均为该对象的属性。然而,这个作用域“对象”无法通过JavaScript代码直接访问,它存在于JavaScript引擎内部。因此,每当试图将this与词法作用域的查找机制混合使用时,务必意识到这是不可行的。
this的四种绑定规则
二、this的绑定规则
this的绑定规则主要可分为以下几类:
2.1 默认绑定
2.2 隐式绑定
2.3 显式绑定
2.4 new绑定
2.1 默认绑定
上述示例中this指向window,这些情况具有共同特征:函数引用不带任何修饰符进行调用。因此,只能应用默认绑定规则,无法适用其他规则。
2.2 隐式绑定
判断隐式绑定的首要规则是检查调用位置是否有上下文对象,即该函数是否被某个对象拥有或包含。例如:

此处的this指向对象obj。类似的情况包括DOM事件绑定,如document.getElementById('xxx').addEventListener('click', function(){xxx});在回调方法中,this指向被选择器选中的元素。这种情况下,可以简单理解为this指向调用方法点(.)前面的那个对象。

2.3 显式绑定
显式绑定在开发过程中应用广泛,借助这些方法可以直接改变当前方法的this指向,使JavaScript语言具备极高的灵活性。主要包含call、apply和bind三种方式,基本使用如下:
function sum() {
console.log(this.a + this.b);
}
var obj1 = {
a: 1,
b: 2
};
var test = sum.bind(obj1);
sum.call(obj1); //3
sum.apply(obj1); //3
test(); //3
注意事项:
call和apply的第一个参数接受的是this对象。call在第二个参数之后可以接受以字符串形式传递的参数,而apply接受的是一个类数组或数组形式的参数列表。
当将null或undefined作为this的绑定对象传入call、apply或bind时,这些值在调用时会被忽略,实际应用的是默认绑定规则。
2.4 new绑定
JavaScript语言中的new操作符与其他面向对象语言中的new操作符存在差异,因为JavaScript中没有传统意义上的类概念。所有函数都可以使用new来调用,这种调用方式称为构造函数调用。在构造函数调用过程中,会自动执行以下操作:
1、创建(或构造)一个全新的对象
2、将该新对象执行[[Prototype]]连接
3、将该新对象绑定到函数调用时的this
4、如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象
构造函数是JavaScript中常用的一种设计模式,示例代码如下:
function Test(a, b) {
this.a = a;
this.b = b;
this.add = function() {
debugger;
console.log(this.a + this.b);
}
}
var cc = new Test(1, 2);
cc.add();
console.log(cc);
在new调用过程中,返回了一个新对象,并且该对象的this指向Test构造函数。

JS读取本地文件时报错或无响应的常见原因
2026-11-05 16:32:31
let、const与var的区别:JavaScript变量声明最佳实践
2026-11-05 14:16:38
JS中直接定义静态二维数组的字面量写法
2026-11-05 14:16:08
JS 怎么查找字符串中所有匹配项的位置
2026-11-05 14:15:53
JavaScript新手常犯的编码错误与最佳实践指南
2026-11-04 22:12:38
