面试官:请解释一下 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();  // 输出:我叫小明

这里sayNameperson对象的方法,所以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个真实场景让你代码更优雅》

相关推荐
Bug生产工厂7 小时前
React支付组件设计与封装:从基础组件到企业级解决方案
前端·react.js·typescript
小喷友7 小时前
阶段三:进阶(Rust 高级特性)
前端·rust
Strayer7 小时前
Tauri2.0打包构建报错
前端
小高0077 小时前
💥💥💥前端“隐藏神技”:15 个高效却鲜为人知的 Web API 大起底
前端·javascript
flyliu7 小时前
再再次去搞懂事件循环
前端·javascript
艾小码7 小时前
还在拍脑袋估工时?3个技巧让你告别加班和延期!
前端·敏捷开发
UrbanJazzerati7 小时前
前端入门:vh、padding、margin、outline、pointer-events
前端·面试
wordbaby7 小时前
一行看懂高阶函数:用 handleConfirm 拿下 DatePicker 回调
前端·react.js
XiaoMu_0017 小时前
基于Node.js和Three.js的3D模型网页预览器
javascript·3d·node.js