JavaScript的this(上下文对象)
七崽爱吃小饼干2026/01/21阅读 2专栏 JavaScript
一、this 是什么?
this 是 JavaScript 中的一个关键字,它不是固定不变的,而是在函数被调用时动态绑定的,指向的是当前函数执行时的上下文对象。
可以简单理解为:this 就是「谁调用了这个函数,this 就指向谁」
二、this 的绑定规则(核心)
this 的指向完全由函数的调用方式决定,不同调用方式对应不同的绑定规则,优先级从低到高依次是:
1. 默认绑定(全局/独立函数调用)
当函数以「独立函数」的形式调用时(没有任何对象前缀),this 会默认绑定到全局对象:
- 浏览器环境:全局对象是
window; - Node.js 环境:全局对象是
global; - 严格模式(
use strict):默认绑定失效,this为undefined。
示例代码:
javascript
// 浏览器环境下的示例
function sayHi() {
console.log(this); // 非严格模式:window;严格模式:undefined
console.log(this.name); // 非严格模式:'张三';严格模式:报错(Cannot read property 'name')
}
var name = '张三'; // 全局变量,挂载在 window 上
sayHi(); // 独立调用,触发默认绑定
2. 隐式绑定(对象方法调用)
当函数作为对象的方法被调用时,this 会指向这个调用函数的对象(即「点前面的对象」)。
示例代码:
javascript
const person = {
name: '李四',
sayHi: function() {
console.log(this.name); // this 指向 person 对象,输出:李四
}
};
person.sayHi(); // 函数作为 person 的方法调用,触发隐式绑定
// 注意:只看最后一层调用的对象
const outer = {
name: '外层',
inner: {
name: '内层',
sayHi: function() {
console.log(this.name); // this 指向 inner,输出:内层
}
}
};
outer.inner.sayHi();
3. 显式绑定(强制指定 this)
通过 call()、apply()、bind() 方法,可以强制指定函数执行时的 this,这是最灵活的绑定方式。
| 方法 | 语法 | 特点 |
|---|---|---|
call() | 函数.call(this指向, 参数1, 参数2...) | 立即执行函数,参数逐个传递 |
apply() | 函数.apply(this指向, [参数1, 参数2...]) | 立即执行函数,参数以数组形式传递 |
bind() | 函数.bind(this指向, 参数1, 参数2...) | 不立即执行,返回一个绑定了 this 的新函数 |
示例代码:
javascript
function sayHi(greet) {
console.log(`${greet},我是${this.name}`);
}
const person = { name: '王五' };
// call 绑定:立即执行,参数逐个传
sayHi.call(person, '你好'); // 输出:你好,我是王五
// apply 绑定:立即执行,参数传数组
sayHi.apply(person, ['哈喽']); // 输出:哈喽,我是王五
// bind 绑定:返回新函数,需手动调用
const bindFn = sayHi.bind(person, '嗨');
bindFn(); // 输出:嗨,我是王五
4. new 绑定(构造函数调用)
当函数作为构造函数(通过 new 关键字调用)时,this 会指向新创建的实例对象。
示例代码:
javascript
function Person(name) {
this.name = name; // this 指向 new 创建的实例
this.sayHi = function() {
console.log('我是' + this.name);
};
}
const p1 = new Person('赵六');
p1.sayHi(); // this 指向 p1,输出:我是赵六
new 执行时的底层逻辑(帮助理解 this 指向):
- 创建一个空的新对象;
- 将新对象的
__proto__指向构造函数的prototype; - 将构造函数的
this绑定到这个新对象; - 执行构造函数的代码(给新对象添加属性/方法);
- 如果构造函数没有返回对象,就返回这个新对象。
5. 箭头函数的 this(特殊情况)
箭头函数没有自己的 this,它的 this 是继承自外层作用域的 this(词法作用域),且永远无法被修改(call/apply/bind 也没用)。
示例代码:
javascript
const person = {
name: '钱七',
normalFn: function() {
console.log(this.name); // 隐式绑定,指向 person,输出:钱七
},
arrowFn: () => {
console.log(this.name); // 继承外层全局的 this,浏览器中输出:undefined(无全局 name)
}
};
person.normalFn();
person.arrowFn();
// 箭头函数的 this 无法被修改
person.arrowFn.call(person); // 依然输出 undefined
三、常见易混场景
1. 函数嵌套/回调函数中的 this
普通函数嵌套时,内层函数的 this 会丢失外层对象的绑定,默认指向全局(严格模式为 undefined):
javascript
const person = {
name: '孙八',
sayHi: function() {
// 内层函数
function innerFn() {
console.log(this.name); // 默认绑定,输出:undefined(浏览器无全局 name)
}
innerFn();
}
};
person.sayHi();
// 解决方法1:用变量保存外层 this
const person2 = {
name: '孙八',
sayHi: function() {
const that = this; // 保存外层 this(指向 person2)
function innerFn() {
console.log(that.name); // 输出:孙八
}
innerFn();
}
};
// 解决方法2:用箭头函数(继承外层 this)
const person3 = {
name: '孙八',
sayHi: function() {
const innerFn = () => {
console.log(this.name); // 继承 sayHi 的 this(指向 person3),输出:孙八
};
innerFn();
}
};
2. DOM 事件中的 this
在 DOM 事件处理函数中,this 默认指向触发事件的 DOM 元素:
html
<button id="btn">点击</button>
<script>
const btn = document.getElementById('btn');
btn.onclick = function() {
console.log(this); // 指向 btn 这个 DOM 元素
};
</script>
总结
this是动态绑定的,核心规则是「谁调用函数,this就指向谁」,优先级:new 绑定>显式绑定(call/apply/bind)>隐式绑定(对象方法)>默认绑定(全局);- 箭头函数没有自己的
this,它的this继承自外层作用域,且无法被修改(bind、call、apply); - 解决嵌套函数
this丢失的问题,可通过「保存外层this(that/self)」或「使用箭头函数」。