🌟面试官让我手撕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️⃣ 显式绑定:强行认亲之术 🤜

用call、apply、bind强行改变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,请优雅地甩出这篇文章,深藏功与名~ 🎩💨

相关推荐
库拉镜像AI牛牛8 分钟前
短剧内容自动化生产:知漫剧工作室落地教程
大数据·服务器·前端·人工智能·语音识别
律宏阔10 分钟前
Flutter 列表图片内存优化:CachedNetworkImage 与 ClipRRect 的取舍
前端·flutter
行者全栈架构师11 分钟前
【鸿蒙心迹】相册文搜图工程化落地:HarmonyOS 7.0 端侧 AI 检索全链路实战与 5 个踩坑解法
前端
律宏阔20 分钟前
Dart 3 Record:解决 Future.wait 异构返回值的类型问题
前端·flutter
花间相见25 分钟前
【后端开发|Redis进阶01】—— Redis分布式锁全解:从SETNX到Redisson看门狗,再到RedLock
后端·面试
Seraphina3630 分钟前
DVWA(XSS Reflected/Stored High,CSRF Low)
前端·xss·csrf
默_笙1 小时前
🍔 中间件不只是打日志:四个钩子、一次短路,和自带的工具
前端·javascript
程序员老赵2 小时前
Docker 部署 Dolibarr:轻松搭建开源 ERP/CRM 平台
运维·前端·后端
星禾元亨2 小时前
同一件事有三份资料,AI 该信哪一份?冲突判定、优先级链与处置流程
前端·人工智能
Dovis(誓平步青云)2 小时前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑