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

相关推荐
betterangela1 分钟前
react基础语法视图层&类组件
前端·javascript·vue.js
小段hy8 分钟前
在小程序中/uni-app中,当没有登录时,点击结算按钮,3s后自动跳转到登录页面
前端·小程序·uni-app
CSDN专家-微编程10 分钟前
UNIAPP圈子社区纯前端万能源码模板 H5小程序APP多端兼容 酷炫UI
前端·小程序·uni-app
冴羽44 分钟前
SvelteKit 最新中文文档教程(2)—— 路由
前端·javascript·svelte
虾球xz1 小时前
游戏引擎学习第153天
javascript·学习·游戏引擎
2401_853275731 小时前
ajax组件是什么
前端·javascript·ajax
若简1 小时前
umi-request使用及原理解析
前端
mmmu1 小时前
网页快速接入 Deepseek,是如此简单!分分钟带你搞定!
前端·deepseek
MariaH1 小时前
一次搞定 Node 的文件操作
前端
知止定静行1 小时前
Maven使用笔记
java·前端·maven