this 指向
this的指向不是在函数定义时确定,而是在函数执行时确定(箭头函数除外),本质是指向调用函数的对象
全局作用域/普通函数
| 执行环境 | this 指向 | 严格模式差异 |
|---|---|---|
| 浏览器 | window 对象 | 普通函数内 this → undefined |
| Node.js | globalThis(函数内) module.exports(全局) | 函数内 this → undefined |
代码开头加
'use strict'后 JS 进入严格模式
js
// 浏览器非严格模式
console.log(this === window); // true
function fn() {
console.log(this);
}
fn(); // window
// 严格模式
'use strict';
function fn2() {
console.log(this);
}
fn2(); // undefined
// Node.js 环境
function fn3() {
console.log(this);
}
fn3(); // globalThis
console.log(this); // module.exports(空对象)对象方法调用
this 指向直接调用方法的对象(方法名前的对象)。方法赋值给变量后,失去原对象绑定,变成全局调用
js
const obj = {
name: '张三',
sayHi() { console.log(this.name); },
child: {
name: '李四',
sayHi() { console.log(this.name); }
}
};
obj.sayHi(); // 张三(this → obj)
obj.child.sayHi(); // 李四(this → obj.child)
const fn = obj.sayHi;
fn(); // undefined(this → window/globalThis)构造函数(new 调用)
this 指向new 创建的实例对象
js
function fun(name) {
this.name = name;
}
f1 = new fun('张三');
console.log(f1.name); // 张三特殊
| 场景 | this 指向 |
|---|---|
| DOM 事件处理函数 | 触发事件的DOM |
| 时器 / 延时器 | 默认全局(严格模式 undefined) |
修改指向
js
const user1 = { name: "张三", sayHi(msg = "") { console.log(`你好,${this.name}。${msg}`); } };
const user2 = { name: "李四" };
// 直接调用,this 指向 user1
user1.sayHi(); // 你好,张三。
// 抽离方法后调用,this 丢失,指向全局
const sayHi = user1.sayHi;
sayHi(); // 你好,undefined。(全局无name属性)上述代码中方法内部已经存在 this 的使用,但是因为方法被抽离后导致 this 丢失。而 JS 提供了 call、apply、bind 三个原生方法,主动改变函数执行时 this 的指向,不在遵循谁调用,this 指向谁的默认规则
| 方法 | 执行时机 | 参数传递 | 核心作用 |
|---|---|---|---|
| call | 立即执行 | 逐个传参 | 临时修改 this 并执行 |
| apply | 立即执行 | 数组传参 | 适合参数数量不确定时 |
| bind | 返回新函数 | 逐个传参(可预填) | 永久绑定 this,按需执行 |
语法:函数.方法(新的this指向, 参数)
call
格式:函数.call(新的this指向, 参数1, 参数2, 参数n)
调用后会立即执行该函数,参数逐个传入。适合固定参数
js
sayHi.call(user2); // 你好,李四。
sayHi.call(user2, "今天天气真不错"); // 你好,李四。今天天气真不错apply
格式:函数.apply(新的this指向, 参数数组)
调用后会立即执行该函数,参数通过数组动态传递。适合参数数量不确定
js
sayHi.apply(user2); // 你好,李四。
let arr = []
arr.push("今天天气真不错");
sayHi.apply(user2, arr); // 你好,李四。今天天气真不错bind
格式:[const/var/let] 变量名 = 函数.bind(新的this指向, 参数1, 参数2, 参数n)
不立即执行函数,返回一个绑定了新 this的新函数;可预填参数(柯里化)
js
let fun1 = sayHi.bind(user2, "今天天气真不错");
fun1(); // 你好,李四。今天天气真不错
fun1("确实不错"); // 你好,李四。今天天气真不错
let fun2 = sayHi.bind(user2);
fun2("今天天气真不错"); // 你好,李四。今天天气真不错
fun2("确实不错"); // 你好,李四。确实不错