你以为的 this 其实不是 this:JS 五种 this 绑定规则 + 面试常见陷阱全解析

115 阅读3分钟

✨ 前言

在 JavaScript 面试中,this 是一个既简单又容易“翻车”的知识点。

你或许会觉得:

“函数不是在对象里定义的吗?那它的 this 不就一定指向对象吗?”

但当你遇到以下这些代码时👇:

const obj = {
  name: '掘金',
  say: () => {
    console.log(this.name); // undefined ❌ 为什么不是“掘金”?
  }
};

obj.say();

你可能就一脸懵了。

别急,这篇文章将带你系统梳理 JavaScript 中 this 的五种绑定规则,每种都配图 + 示例,避免你再掉入 this 的坑


🧠 一图总览:JavaScript 中的 this 绑定规则

绑定方式使用方式this 指向适用场景举例
默认绑定普通函数调用非严格模式下为 window,严格模式下为 undefinedfn()
隐式绑定通过对象调用方法调用者对象obj.fn()
显式绑定使用 call / apply / bind显式传入的对象fn.call(obj)
new 绑定使用 new 调用函数新创建的实例对象new Fn()
箭头函数绑定箭头函数定义时所在作用域的 this,不可更改()=> this.name

1️⃣ 默认绑定:谁也没调用你

function foo() {
  console.log(this); // 非严格模式:window;严格模式:undefined
}

foo();

解释:
函数被“独立调用”时,它的 this 默认指向全局对象(浏览器是 window,Node.js 是 global),严格模式下则是 undefined


2️⃣ 隐式绑定:谁调用我,我就是谁

const obj = {
  name: '掘金',
  say() {
    console.log(this.name);
  }
};

obj.say(); // 输出:掘金 ✅

解释:
当函数通过对象调用时,this 会自动绑定为这个对象,即“谁点出来我,this 就是谁”。


3️⃣ 显式绑定:我指定你是谁

function greet() {
  console.log(this.name);
}

const user = { name: '掘金' };

greet.call(user); // 输出:掘金 ✅

解释:
使用 call / apply / bind 可以直接指定 this 的指向。


4️⃣ new 绑定:我就是新对象

function Person(name) {
  this.name = name;
}
const p = new Person('掘金');
console.log(p.name); // 输出:掘金 ✅

解释:
new 会创建一个新的对象,并把函数里的 this 指向它。


5️⃣ 箭头函数绑定:出生那刻就决定了命运

const obj = {
  name: '掘金',
  say: () => {
    console.log(this.name); // undefined ❌
  }
};
obj.say();

解释:
箭头函数没有自己的 this,它会捕获定义时外层作用域的 this,且无法被 callbind 改变。

比如上述代码中 say 是在全局作用域中定义的(对象字面量并不创建作用域),所以 thiswindowundefined


🎯 面试常见 this 陷阱

❌ 陷阱1:箭头函数放对象里就以为能用 this

const obj = {
  name: '掘金',
  say: () => {
    console.log(this.name);
  }
};
obj.say(); // ❌ undefined

✅ 改法:

say() {
  console.log(this.name); // 掘金
}

❌ 陷阱2:函数提前拿出来调用就丢失了 this

const obj = {
  name: '掘金',
  say() {
    console.log(this.name);
  }
};

const fn = obj.say;
fn(); // ❌ undefined (默认绑定)

✅ 改法:

fn.call(obj); // 显式绑定 this

📌 结语

JavaScript 的 this 看似“玄学”,实则有规可循。你只要掌握这五种绑定规则:

  • 默认绑定

  • 隐式绑定

  • 显式绑定

  • new 绑定

  • 箭头函数绑定(捕获定义时的 this)

加上常见的陷阱训练,就能应对绝大多数面试场景。


🔗 最后附上一句面试金句:

判断 this 是谁,关键是看“函数是怎么调用的”,不是它在哪里定义的,也不是它长得像谁。