"我不是你以为的我,我是谁,取决于你怎么叫我。"
------ this 的自我认知觉醒时刻
🧠 一、什么是 this?
在 JavaScript 中,this
是一种运行时绑定,它代表的是函数被调用时的上下文对象。
不是定义位置、不是写在哪儿的对象、不是函数自己。
只有一个真理:
谁调用我,我就指向谁!
🧭 二、this 的五大使用场景(含画面记忆)
1️⃣ 普通函数调用:没人叫我,我就随便跑
scss
function say() {
console.log(this);
}
say(); // 浏览器:window,严格模式:undefined
📌 图像记忆:
"没人指定我,我就回家(window)喝茶;严格模式下我连家都没有,只能飘着。"
2️⃣ 对象.方法():谁叫我,我就听谁的
javascript
const obj = {
name: '小吴',
say() {
console.log(this.name);
}
};
obj.say(); // 小吴
📌 图像记忆:
"老板喊我发言,我当然听老板的!"
3️⃣ call/apply/bind:强行换老板
javascript
function show() {
console.log(this.name);
}
show.call({ name: '小吴' }); // 小吴
📌 图像记忆:
"有人强行塞我个老板,那我就换部门。"
4️⃣ 构造函数(new):刚出生,我自己就是 this
ini
function Person(name) {
this.name = name;
}
const p = new Person('小吴');
console.log(p.name); // 小吴
📌 图像记忆:
"我是谁?我是刚出生的我,我的 this 是我自己。"
5️⃣ 箭头函数:我听妈的,不听你
javascript
const obj = {
name: '小吴',
say: () => {
console.log(this.name);
}
};
obj.say(); // undefined
📌 图像记忆:
"我是箭头函数,从出生起就认了'妈',你再怎么喊我,我也不换妈。"
🧪 三、记忆表格总结
使用方式 | this 指向 | 图像记忆关键词 |
---|---|---|
普通函数调用 | window 或 undefined | "没人叫我我就漂着" |
对象.方法() | 谁调用我我就指向谁 | "谁点我我听谁" |
call/apply/bind | 显式绑定的对象 | "换老板、改指向" |
构造函数 new | 新对象本身 | "新出生就是我" |
箭头函数 | 定义时所在作用域的 this | "妈宝函数,死认妈" |
🔥 四、实战题巩固理解(附解析)
下面是一套由浅入深的实战题,每一题都附有简要解释,帮你彻底掌握 this!
✅ 题 1:全局函数的 this
javascript
'use strict';
function whoAmI() {
console.log(this);
}
whoAmI();
✅ 输出:undefined
🧠 原因:严格模式下,没有调用者,this 默认为 undefined。
✅ 题 2:对象点方法
javascript
const obj = {
name: '小吴',
say() {
console.log(this.name);
}
};
obj.say();
✅ 输出:小吴
🧠 原因:obj.say()
,this 就是 obj。
✅ 题 3:函数脱壳
ini
const obj = {
name: '小吴',
say() {
console.log(this.name);
}
};
const fn = obj.say;
fn();
✅ 输出:undefined
(浏览器下也许是 '全局'
)
🧠 原因:函数独立调用,this 默认指向 window / undefined。
✅ 题 4:箭头函数继承外层 this
javascript
const obj = {
name: '小吴',
say() {
return () => {
console.log(this.name);
};
}
};
obj.say()();
✅ 输出:小吴
🧠 原因:箭头函数继承 say()
的 this,也就是 obj。
✅ 题 5:箭头函数用 bind 改不了 this
ini
const arrow = () => {
console.log(this.name);
};
arrow.call({ name: '小吴' });
✅ 输出:undefined
🧠 原因:箭头函数 this 固定为定义时作用域,call 没用!
✅ 题 6:构造函数 this
ini
function Person(name) {
this.name = name;
}
const p = new Person('小吴');
console.log(p.name);
✅ 输出:小吴
🧠 原因:new
调用,this 是新创建对象 p。
✅ 题 7:setTimeout 的坑
javascript
const obj = {
name: '小吴',
say() {
setTimeout(function () {
console.log(this.name);
}, 100);
}
};
obj.say();
✅ 输出:undefined
🧠 原因:普通函数作为 setTimeout
回调,this 不是 obj,而是 window。
✅ 题 8:setTimeout 改进版(箭头函数)
javascript
const obj = {
name: '小吴',
say() {
setTimeout(() => {
console.log(this.name);
}, 100);
}
};
obj.say();
✅ 输出:小吴
🧠 原因:箭头函数继承 say 方法的 this。
✅ 题 9:bind 后的 this
ini
const obj = {
name: '小吴'
};
function show() {
console.log(this.name);
}
const bound = show.bind(obj);
bound();
✅ 输出:小吴
🧠 原因:bind 固定了 this 为 obj。
✅ 题 10:bind 和 new 谁更强?
ini
function Person(name) {
this.name = name;
}
const Bound = Person.bind({ name: '假名' });
const p = new Bound('小吴');
console.log(p.name);
✅ 输出:小吴
🧠 原因:new
优先于 bind,忽略了 bind 指定的 this。
🎓 五、提升总结:this 背后的编程思想
this 是 JS 中最能体现"执行时上下文"的一个关键词。
如果你搞懂了 this,你就能掌握:
- 函数执行上下文
- 闭包与作用域链
- 箭头函数的行为特性
- new 和原型链关系
- call / apply / bind 的原理
✅ 一句话终极记忆法
"this 指向谁,不是看函数在哪写,而是看它怎么被调用。"