🌟面试官让我手撕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,请优雅地甩出这篇文章,深藏功与名~ 🎩💨

相关推荐
2501_944521592 小时前
Ramda 跨端三方库仓颉适配全流程
开发语言·javascript·flutter·php
考研保研资料分享4 小时前
211公共管理保研北航行政管理:五校考核、论文追问与择校复盘
面试
考研保研资料分享4 小时前
985工科跨保上财应用统计:数学笔试、匿名面试与机试复盘
面试·职场和发展
Ken_11154 小时前
小体积附件下载正常,大附件下载异常
javascript
变与不变8065 小时前
jQuery怎么使用
前端·javascript
神膘护体小月半5 小时前
flex 布局的 order 属性
前端·css
paopaokaka_luck5 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
仰望.5 小时前
vue 表格组件 vxe-table 树表格懒加载支持拖拽排序的详细用法
前端·javascript·vue.js·vxe-table
前端 贾公子5 小时前
vite-plugin-uni-manifest 升级指南
前端
小码哥_常5 小时前
iPhone 用户传了张 HEIC,我的前端崩了
前端