🌟面试官让我手撕this,结果我当场表演了段"指鹿为马"...

引言

大家好,我是刚被面试官用this连环拷打的大三前端菜狗🐶。今天遇到一道堪称"this界修罗场"的题目,让我彻底明白------在JavaScript的世界里,this就是个"变色龙"!(别打我,看完你就懂)


一、先上"刑场真题" 🚨

(建议先不要看答案,自己脑补输出结果)

javascript 复制代码
var a = 10;
var foo = {
  a: 20,
  b: function () {
    var a = 30;
    return this.a;
  },
  c: () => {
    var a = 40;
    return this.a;
  },
}

var d = { a: 50 };

console.log(a);         // ?
console.log(foo.b());    // ?
console.log(foo.c());    // ?
console.log(foo.b.bind(d)()); // ?
console.log(foo.c.bind(d)()); // ?

答案揭晓前,先带大家修炼"this心法"!


二、this四大定律 📜

1️⃣ 默认绑定:孤狼模式 🐺

当函数"裸奔"调用时,this默认指向全局对象:

  • 浏览器window
  • Node环境global(但模块作用域中默认是undefined!)
javascript 复制代码
function showThis() {
  console.log(this === window); 
}
showThis(); // 浏览器中输出 true 🪟

⚠️ 陷阱警告

javascript 复制代码
'use strict'; // 严格模式下全局this是undefined!
function strictThis() {
  console.log(this); 
}
strictThis(); // undefined 🚫

2️⃣ 隐式绑定:谁调用就认谁做爹 👨👦

当函数被对象"领养"时,this指向调用它的最近对象

javascript 复制代码
const family = {
  father: '👨',
  say: function() {
    console.log(this.father);
  }
};
family.say(); // 输出 👨(this指向family)

但! 如果把方法赋值给变量...

javascript 复制代码
const lostChild = family.say;
lostChild(); // 输出 undefined 😭(this指向全局)

3️⃣ 显式绑定:强行认亲之术 🤜

callapplybind强行改变this指向:

javascript 复制代码
const orphan = { father: '🏠孤儿院' };

family.say.call(orphan);    // 🏠孤儿院
family.say.apply(orphan);   // 🏠孤儿院
const boundSay = family.say.bind(orphan);
boundSay();                 // 🏠孤儿院

🔍 区别小课堂

  • call:参数一个个传 (thisArg, arg1, arg2...)
  • apply:参数用数组传 (thisArg, [args])
  • bind:返回新函数,需要再次调用

4️⃣ new绑定:无中生有造对象 🧙♂️

构造函数中,this指向新创建的实例

javascript 复制代码
function Person(name) {
  this.name = name;
}
const baby = new Person('👶');
console.log(baby.name); // 👶

三、箭头函数------this界的佛系青年 🧘♂️

箭头函数的this定义时就确定了,像"刻在DNA里"一样无法改变!

🚫 三大禁忌:

  1. 不能用call/apply/bind修改this
  2. 不能作为构造函数
  3. 没有自己的arguments
javascript 复制代码
const obj = {
  a: 1,
  normalFunc: function() {
    console.log(this.a); // 正常人的this 😎
  },
  arrowFunc: () => {
    console.log(this.a); // 佛系青年的this 🧘♂️
  }
};

obj.normalFunc(); // 1(this指向obj)
obj.arrowFunc();  // undefined(this指向外层全局)

四、浏览器 vs Node环境差异 🌐

全局变量差异:

  • 浏览器var a = 1 → 挂载到window
  • Node :每个文件都是模块,var a = 1不属于global
javascript 复制代码
// test.js
var a = 1;
console.log(global.a); // Node输出 undefined
console.log(window.a); // 浏览器输出 1

箭头函数实战差异:

javascript 复制代码
const obj = {
  arrow: () => console.log(this)
};

obj.arrow(); 
// 浏览器:Window(外层是全局)
// Node:{}(外层是模块作用域的this,空对象)

五、终极解密面试题 🕵️♂️

现在带着心法回头看题目:

javascript 复制代码
// 全局a=10(浏览器挂载到window)
var a = 10;

var foo = {
  a: 20,
  b: function () {      // 普通函数,this看调用者
    var a = 30;        // 烟雾弹!和this无关
    return this.a;
  },
  c: () => {           // 箭头函数,this继承定义时的外层(全局)
    var a = 40;        // 烟雾弹×2
    return this.a;
  },
};

var d = { a: 50 };

console.log(a); // 10 ✅(直接访问全局a)

console.log(foo.b()); // 20 ✅(this指向调用者foo)

console.log(foo.c()); // 10(浏览器)或undefined(Node)✅  
// 箭头函数this指向全局,浏览器中window.a=10,Node无全局a

console.log(foo.b.bind(d)()); // 50 ✅(bind强行指向d)

console.log(foo.c.bind(d)()); // 同上结果,bind对箭头函数无效!✅

六、防坑指南 🚧

  1. 避免在对象方法中使用箭头函数(除非刻意指向全局)
  2. 回调函数中的this陷阱 (用箭头函数或bind固定this)
  3. 严格模式警惕默认绑定(全局this变undefined)

七、灵魂总结 💡

"普通函数看调用,箭头函数看定义,显式绑定显神通,new个对象最安心"

下次面试再遇到this,请优雅地甩出这篇文章,深藏功与名~ 🎩💨

相关推荐
新手小新几秒前
C++游戏开发(2)
开发语言·前端·c++
我不吃饼干26 分钟前
【TypeScript】三分钟让 Trae、Cursor 用上你自己的 MCP
前端·typescript·trae
小杨同学yx1 小时前
前端三剑客之Css---day3
前端·css
星月心城2 小时前
Promise之什么是promise?(01)
javascript
二川bro3 小时前
第二篇:Three.js核心三要素:场景、相机、渲染器
开发语言·javascript·数码相机
Mintopia3 小时前
🧱 用三维点亮前端宇宙:构建你自己的 Three.js 组件库
前端·javascript·three.js
故事与九3 小时前
vue3使用vue-pdf-embed实现前端PDF在线预览
前端·vue.js·pdf
小西↬3 小时前
vite+vue3+websocket处理音频流发送到后端
javascript·websocket·音视频
Mintopia4 小时前
🚀 顶点-面碰撞检测之诗:用牛顿法追寻命运的交点
前端·javascript·计算机图形学
wb1894 小时前
企业WEB应用服务器TOMCAT
运维·前端·笔记·tomcat·云计算