"this 绑定 " 是前端面试最常考的 JavaScript 核心机制之一。
出题方式通常是 ------ 给一段带有函数 / 对象 / 箭头函数 / call / bind 的代码,让你说出输出结果并解释。
🌟 一、基础题:全局 this
js
function foo() {
console.log(this);
}
foo();
✅ 输出:
在浏览器中:window
在 Node.js 中:undefined(因为模块是严格模式)
🧠 解析:
普通函数调用,this 默认指向 全局对象(非严格模式) 。
严格模式下为 undefined。
🌟 二、对象方法调用
js
var name = 'window';
const obj = {
name: 'obj',
getName() {
console.log(this.name);
}
};
obj.getName();
✅ 输出:
obj
🧠 解析:
getName 被作为对象方法调用,this 指向调用它的对象 ------ obj。
🌟 三、丢失 this(最常考陷阱)
js
var name = 'window';
const obj = {
name: 'obj',
getName() {
console.log(this.name);
}
};
const fn = obj.getName;
fn();
✅ 输出:
window
🧠 解析:
fn 是普通函数引用调用,不再与 obj 绑定;
所以 this 回到默认绑定 ------ window(或严格模式下为 undefined)。
💡 面试加分点:
可以通过
fn.bind(obj)修正 this。
🌟 四、箭头函数不绑定 this
js
var name = 'window';
const obj = {
name: 'obj',
getName: () => {
console.log(this.name);
}
};
obj.getName();
✅ 输出:
window
🧠 解析:
箭头函数没有自己的 this,
它的 this 来自定义时的词法环境(此处是全局作用域)。
🌟 五、嵌套箭头函数捕获外层 this
js
var name = 'window';
const obj = {
name: 'obj',
getName() {
return () => console.log(this.name);
}
};
const fn = obj.getName();
fn();
✅ 输出:
obj
🧠 解析:
getName()是普通方法调用,this指向obj;- 箭头函数捕获定义时的
this(即obj); - 所以最终输出
'obj'。
🌟 六、call / apply / bind 显式绑定
js
function foo() {
console.log(this.name);
}
const obj = { name: 'obj' };
foo.call(obj);
foo.apply(obj);
const bar = foo.bind(obj);
bar();
✅ 输出:
obj
obj
obj
🧠 解析:
call、apply、bind 都能显式绑定 this。
🌟 七、bind 后再 call(加分题)
js
function foo() {
console.log(this.name);
}
const obj1 = { name: 'obj1' };
const obj2 = { name: 'obj2' };
const fn = foo.bind(obj1);
fn.call(obj2);
✅ 输出:
obj1
🧠 解析:
bind 一旦绑定 this,之后无论怎么调用,都不会被改变。
bind 的 this 绑定优先级最高。
🌟 八、构造函数中的 this
js
function Foo(name) {
this.name = name;
}
const a = new Foo('A');
const b = new Foo('B');
console.log(a.name, b.name);
✅ 输出:
A B
🧠 解析:
-
使用
new调用函数时:- 创建一个新对象;
- 绑定 this 到这个新对象;
- 执行函数体;
- 返回新对象(除非显式返回对象)。
🌟 九、new 与 bind 一起用(必问陷阱)
js
function Foo(name) {
this.name = name;
}
const obj = { name: 'obj' };
const Bar = Foo.bind(obj);
const b = new Bar('B');
console.log(b.name);
console.log(obj.name);
✅ 输出:
B
obj
🧠 解析:
当函数通过 new 调用时,this 指向新创建的实例对象,
即使函数被 bind 绑定过,也会被 new 覆盖。
因此:
b的name是'B'- 原
obj不受影响。
🌟 十、隐式丢失(链式调用陷阱)
js
var name = 'window';
const obj1 = {
name: 'obj1',
foo() {
console.log(this.name);
}
};
const obj2 = { name: 'obj2', foo: obj1.foo };
const fn = obj1.foo;
obj1.foo(); // ?
obj2.foo(); // ?
fn(); // ?
✅ 输出:
obj1
obj2
window
🧠 解析:
obj1.foo()→ 调用者是 obj1 → this = obj1obj2.foo()→ 调用者是 obj2 → this = obj2fn()→ 普通函数调用 → this = window
🎯 this 绑定优先级总结(面试口诀)
new 绑定 > 显式绑定(bind/call/apply) > 隐式绑定(obj.foo()) > 默认绑定(window 或 undefined)
🧠 面试建议:
面试官问 "this 输出什么" 时,
你可以快速按这个思路走:
1️⃣ 看调用方式 (普通 / 对象调用 / 构造 / 箭头)
2️⃣ 判断 this 来源 (隐式 / 显式 / 词法捕获)
3️⃣ 考虑优先级(new > bind > call > 隐式 > 默认)
。