你真的懂 this 吗?99% 的初学者都踩过的 JavaScript 大坑!

142 阅读3分钟

“为什么我在控制台打印 this,结果和我想象的不一样?”
“为什么同样的函数,this 指向却变了?”
“箭头函数的 this 又是什么鬼?”
如果你也有这些疑惑,恭喜你,今天这篇文章就是为你量身定制的!

一、this 到底是什么?

在 JavaScript 里,this 是一个“代词”,它指向某个对象,但具体指向谁,完全取决于函数是怎么被调用的。
很多初学者会把 this 理解成“当前对象”,但其实这只是表象。this 的真正指向,是由调用方式决定的。

为什么要有 this?

this 的出现,让我们可以更优雅地在函数内部引用外部对象,代码更简洁、复用性更强。比如:

function sayName() {
  console.log(this.name);
}
const person = { name: '小明', sayName };
person.sayName(); // 输出:小明

如果没有 this,每次都要手动传对象,代码会变得很啰嗦。

二、this 的五大绑定规则

1. 默认绑定

最常见的坑!当函数被独立调用时,this 默认指向全局对象(浏览器里是 window,严格模式下是 undefined)。

function foo() {
  console.log(this); // 浏览器下输出 window
}
foo();

2. 隐式绑定

当函数作为对象的方法被调用时,this 指向调用它的那个对象。

const obj = {
  a: 2,
  foo: function() {
    console.log(this.a);
  }
};
obj.foo(); // 输出 2

注意隐式丢失:

const obj = {
  a: 2,
  foo: function() {
    console.log(this.a);
  }
};
const bar = obj.foo;
bar(); // 输出 window.a 或 undefined

bar 只是单纯引用了 obj.foo,此时 this 又回到了默认绑定。

3. 显式绑定

callapplybind 可以强行指定 this 的指向。

function foo(x, y) {
  console.log(this.a, x + y);
}
const obj = { a: 1 };
foo.call(obj, 1, 2); // 1 3
foo.apply(obj, [1, 2]); // 1 3
const bar = foo.bind(obj, 2, 3);
bar(); // 1 5
  • callapply 立即调用函数,区别在于参数传递方式。
  • bind 返回一个新函数,永久绑定 this

4. new 绑定

当函数通过 new 关键字调用时,this 指向新创建的实例对象。

function Person() {
  this.name = '路明非';
  this.age = 18;
  console.log(this);
}
const p1 = new Person(); // this 指向 p1

5. 箭头函数的 this

箭头函数没有自己的 this,它的 this 取决于它外层最近的非箭头函数的 this

var a = 1;
var obj = {
  a: 2,
  bar: function() {
    const baz = () => {
      console.log(this.a);
    }
    baz();
  }
};
obj.bar(); // 输出 2

这里 bazthis 继承自 bar,而 barthisobj

三、this 的常见面试陷阱

1. 多层对象调用

var a = 1;
function foo() {
  console.log(this.a);
}
var obj = {
  a: 2,
  foo: foo
};
var obj2 = {
  a: 3,
  obj: obj
};
obj2.obj.foo(); // 输出 2

foo 的调用者是 obj2.obj,但实际调用的是 obj,所以 this 指向 obj

2. 闭包与 this

var a = 3;
function foo() {
  var a = 2;
  function bar() {
    var a = 1;
    console.log(this.a);
  }
  bar();
}
foo(); // 输出 3

bar 独立调用,this 指向全局对象。

3. 严格模式下的 this

在严格模式下,独立调用函数时,thisundefined,而不是 window

'use strict';
function foo() {
  console.log(this);
}
foo(); // 输出 undefined

四、this 的实际开发建议

  1. 避免 this 混乱:多用箭头函数或 bind 明确指定 this
  2. 对象方法调用:不要轻易把对象方法赋值给变量再调用,容易丢失 this
  3. 构造函数和类:用 new 创建实例时,记得 this 指向新对象。
  4. 面试题多练习:多写代码、多调试,才能真正理解 this 的指向。

五、总结

this 是 JavaScript 里最容易让初学者迷惑的知识点之一。它的指向并不是在函数定义时决定的,而是在函数调用时动态绑定的。掌握了 this 的五大绑定规则,再配合实际代码练习,你一定能攻克这个大坑!