1.this指向
什么是this指向?
在 JavaScript中,this的指向取决于函数被调用的方式,而非定义的位置
1.1常见的this
- 独立函数
函数独立调用时,this指向全局对象(浏览器中为 window,Node.js中为global)。
javascript
function show() {
console.log(this); // window(非严格模式)
}
show();
严格模式下为undefined
javascript
function show() {
"use strict"
console.log(this); // undefined
}
show(); // 如果window.show()那么此时的this指向的就是window
- 对象函数
函数作为对象方法调用时,this 指向调用它的对象
javascript
const user = {
name: "Alice",
greet() {
console.log(`Hello, ${this.name}!`); // Hello, Alice!
}
};
user.greet();
方法被分离后调用会导致this丢失
javascript
const func = user.greet;
func(); // ❌ 错误:this 丢失(指向 window/undefined)
- 箭头函数
箭头函数的this定义:箭头函数的this是在定义函数时绑定的,不是在执行过程中绑定的。简单的说,函数在定义时,this就继承了定义函数的对象。
箭头函数内的this就是箭头函数外的那个this为什么?
注意:箭头函数没有自己的this
javascript
const obj = {
name: "Dave",
regularFunc: function() {
console.log(this.name); // Dave(隐式绑定)
},
arrowFunc: () => {
console.log(this.name); // 空(继承外层 this)window上没有name
}
};
obj.regularFunc();
obj.arrowFunc();
javascript
let name = "123";
let person = {
name: "456",
fn1: function() {
// 这边的this和下面的setTimeout函数下的this相等
let that = this;
setTimeout(() => {
console.log(this.name, that === this); // '456' true
}, 0);
},
fn2: function() {
// 这边的this和下面的setTimeout函数下的this不相等
let that = this;
setTimeout(function() {
console.log(this.name, that === this); // '123' false
}, 0);
},
};
person.fn1(); // '456' true
person.fn2(); // '123' false
- DOM节点
非严格模式
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>最编程 创未来</title>
</head>
<body>
<button>变色</button>
<script>
let elements = document.getElementsByTagName("button")[0];
elements.addEventListener(
"click",
function () {
this.style.backgroundColor = "#A5D9F3";
},
false
);
</script>
</body>
</html>

严格模式
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>最编程 创未来</title>
</head>
<body>
<button>变色</button>
<script>
'use strict'
var elements = document.getElementsByTagName("button")[0];
elements.addEventListener(
"click",
function () {
console.log(this)
this.style.backgroundColor = "#A5D9F3";
},
false
);
</script>
</body>
</html>

- 内联事件函数
当代码被内联处理函数调用时,它的this指向监听器所在的DOM元素,不区分严格或非严格模式
javascript
<button onclick="console.log(this)">点击测试</button> <!-- <button onclick="console.log(this)">点击测试</button> -->
当代码被包括在函数内部执行时,其this指向等同于函数直接调用的情况,即在非严格模式指向全局对象window
javascript
<button onclick="(function() { console.log(this) })()">点击测试</button> <!-- Window {window: Window, self: Window, document: document, name: '最编程', location: Location, ...} -->
当代码被包括在函数内部执行时,其this指向等同于函数直接调用的情况,在严格模式指向undefined
javascript
<button onclick="(function() {'use strict'; console.log(this) })()">点击测试</button> <!-- undefined -->
- 构造函数
构造函数中,this 指向新创建的实例对象Person{}
javascript
function Person(name) {
this.name = name;
}
const charlie = new Person("金小子");
console.log(charlie.name); // 金小子
javascript
// 伪代码展示 new 的操作流程
const charlie = new Person("金小子");
// 实际发生的步骤:
// 1. 创建新对象
const tempObj = {};
// 2. 设置原型链
tempObj.__proto__ = Person.prototype;
// 3. 将 this 绑定到新对象并执行构造函数
Person.call(tempObj, "金小子"); // 此时构造函数内的 this = tempObj
// 4. 返回新对象
const charlie = tempObj;
以上就是常见的this指向,那么接下来来看改变this指向的方式。
2. call、apply、bind
JavaScript 的 call、apply 和 bind 都是用于显式绑定函数执行时的 this 指向。
三者核心区别:
● call:立即执行函数,逐个传递参数
● apply:立即执行函数,数组形式传递参数
● bind:不立即执行,返回新函数(永久绑定 this 和部分参数)
2.1 call
call
语法
javascript
func.call(thisArg, arg1, arg2, ...)
例子
javascript
function greet(message) {
console.log(`${message}, ${this.name}!`);
}
const person = { name: "Alice" };
// 将 greet 的 this 指向 person,并传递参数
greet.call(person, "Hello"); // 输出: "Hello, Alice!"
● greet 中的 this 原本指向全局(如 window),但通过 call 将 this 绑定到 person 对象
● "Hello" 作为参数逐个传递
2.2 apply
语法
javascript
func.apply(thisArg, [argsArray])
示例
javascript
function introduce(age, job) {
console.log(`${this.name} is ${age} years old and works as a ${job}.`);
}
const person = { name: "Bob" };
// 将 introduce 的 this 指向 person,参数通过数组传递
introduce.apply(person, [30, "developer"]); // 输出: "Bob is 30 years old and works as a developer."
● 参数以数组 [30, "developer"] 形式传递(适合动态参数场景)
● 等同于 introduce.call(person, 30, "developer")
2.3 bind
语法
javascript
const newFunc = func.bind(thisArg, arg1, arg2, ...)
newFunc()
示例
javascript
function logHobby(hobby1, hobby2) {
console.log(`${this.name} likes ${hobby1} and ${hobby2}.`);
}
const person = { name: "Charlie" };
// 创建新函数,永久绑定 this 和部分参数
const boundFunc = logHobby.bind(person, "hiking");
// 调用新函数时只需传入剩余参数
boundFunc("reading"); // 输出: "Charlie likes hiking and reading."
● bind 返回一个新函数 boundFunc,其 this 永久绑定为 person
● "hiking" 被预设为第一个参数,调用时只需传递剩余参数
总结
| 方法 | 执行时机 | 参数形式 | 是否返回新函数 |
|---|---|---|---|
| call | 立即执行 | 逐个参数 (arg1, arg2) | ❌ |
| apply | 立即执行 | 数组 ([args]) | ❌ |
| bind | 延迟执行 | 逐个参数(可部分预设) | ✅ |
🌟 核心总结
this 指向是 JavaScript 中核心且易混淆的知识点,其本质遵循「调用决定指向」的原则(箭头函数除外):
普通函数:this 指向调用它的对象,独立调用时指向全局(严格模式为 undefined);
箭头函数:无自有 this,继承定义时外层作用域的 this;
构造函数 / 事件处理:this 分别指向实例对象、触发事件的 DOM 元素;
显式绑定:call/apply/bind 可强制修改 this 指向,三者仅在「执行时机、参数形式」上有差异(call/apply 立即执行,bind 返回新函数)。
📌 实践建议
日常开发中,优先通过「对象方法调用」「箭头函数」「bind 绑定」明确 this 指向,避免全局 this 污染;
处理动态参数时用 apply,需预设参数 / 延迟执行时用 bind,简单传参优先 call;
严格模式下需格外注意独立函数的 this 指向(变为 undefined),避免意外报错。
🎯 记忆口诀
this 指向:「谁调用,指向谁;箭头函数,找外层;构造 /new,指实例;显式绑定,听 call/apply/bind」;
绑定三兄弟:「call 逐个传,apply 数组传,bind 绑完等调用」。