面试官:请解释一下 JS 的 this 指向。别慌,看完这篇让你对答如流!

大家好啊!我是大华! 经常面试的朋友应该知道,JavaScript中的this指向是一个非常经典的问题。很多朋友一听到this就头皮发麻。所以来整理了一下这篇文章。

先来个最简单粗暴的理解:this就是一个指向函数执行时所属对象的引用。就是:谁调用这个函数,this就指向谁。

我们看几个真实场景就明白了!

场景1:普通函数调用

javascript 复制代码
function sayHello() {
  console.log(this === window);
}

sayHello();  // 输出:true

这里直接调用sayHello,相当于window.sayHello(),所以this指向window。

但在严格模式下:

javascript 复制代码
"use strict";
function sayHello() {
  console.log(this);
}

sayHello();  // 输出:undefined

看,严格模式下this就是undefined,避免了指向全局对象的问题。

场景2:对象方法调用

javascript 复制代码
const person = {
  name: "小明",
  sayName: function() {
    console.log("我叫" + this.name);
  }
};

person.sayName();  // 输出:我叫小明

这里sayName是person对象的方法,所以this指向person对象。

但是注意这个坑:

javascript 复制代码
const person = {
  name: "小明",
  sayName: function() {
    console.log("我叫" + this.name);
  }
};

const say = person.sayName;
say();  // 输出:我叫undefined

为什么?因为say()是直接调用的,this指向了window,而window没有name属性。

场景3:构造函数调用

javascript 复制代码
function Person(name) {
  this.name = name;
}

const xiaoming = new Person("小明");
console.log(xiaoming.name);  // 输出:小明

使用new操作符时,this指向新创建的对象实例。

场景4:箭头函数

这是ES6的新特性,也是面试常考点:

javascript 复制代码
const person = {
  name: "小明",
  hobbies: ["篮球", "游泳"],
  showHobbies: function() {
    this.hobbies.forEach(function(hobby) {
      console.log(this.name + "喜欢" + hobby);
    });
  }
};

person.showHobbies();  
// 输出:undefined喜欢篮球
// 输出:undefined喜欢游泳

为什么是undefined?因为forEach里的回调函数是独立调用的,this指向window。

用箭头函数解决:

javascript 复制代码
const person = {
  name: "小明",
  hobbies: ["篮球", "游泳"],
  showHobbies: function() {
    this.hobbies.forEach((hobby) => {
      console.log(this.name + "喜欢" + hobby);
    });
  }
};

person.showHobbies();  
// 输出:小明喜欢篮球
// 输出:小明喜欢游泳

箭头函数的this继承自外层作用域,所以这里指向person对象。

场景5:改变this指向

有时候我们需要手动改变this指向,JavaScript提供了3个方法:

call方法:

javascript 复制代码
function introduce(age, hobby) {
  console.log(`我是${this.name},今年${age}岁,喜欢${hobby}`);
}

const person = { name: "小明" };

introduce.call(person, 18, "篮球");
// 输出:我是小明,今年18岁,喜欢篮球

apply方法:

javascript 复制代码
function introduce(age, hobby) {
  console.log(`我是${this.name},今年${age}岁,喜欢${hobby}`);
}

const person = { name: "小明" };

introduce.apply(person, [18, "篮球"]);
// 输出:我是小明,今年18岁,喜欢篮球

bind方法:

javascript 复制代码
function introduce(age, hobby) {
  console.log(`我是${this.name},今年${age}岁,喜欢${hobby}`);
}

const person = { name: "小明" };
const introduceXiaoming = introduce.bind(person, 18);

introduceXiaoming("游泳");  
// 输出:我是小明,今年18岁,喜欢游泳

记住这个判断顺序,面试时超有用:

  1. 函数是否用new调用?是 → this指向新对象
  2. 是否用call/apply/bind指定this?是 → this指向指定对象
  3. 是否是箭头函数?是 → this继承外层作用域
  4. 是否是对象的方法?是 → this指向该对象
  5. 以上都不是 → this指向全局对象(严格模式下为undefined)

总结

this指向其实就一句话:看函数是怎么被调用的,而不是在哪里定义的。

记住几个关键点:

  • 普通函数调用:指向全局对象(或undefined)
  • 对象方法调用:指向该对象
  • 构造函数调用:指向新创建的实例
  • 箭头函数:继承外层作用域的this
  • 可以用call/apply/bind手动改变this指向

下次面试官再问this,你就可以自信地回答了!记得多写代码多练习,实践出真知哦~

希望这篇文章对你有帮助!如果有任何问题,欢迎留言讨论~

📌往期精彩

《写给小公司前端的 UI 规范:别让页面丑得自己都看不下去》

《只会写 Mapper 就敢说会 MyBatis?面试官:原理都没懂》

《别再手写判空了!SpringBoot 自带的 20 个高效工具类》

《别学23种了!Java项目中最常用的6个设计模式,附案例》

《Vue3+TS设计模式:5个真实场景让你代码更优雅》

相关推荐
子兮曰4 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰4 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万4 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝4 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋4 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁4 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄4 天前
JavaScript 隐式全局变量解析
javascript
汉堡大王95274 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大4 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师4 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端