“为什么我在控制台打印 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. 显式绑定
用 call、apply、bind 可以强行指定 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
call和apply立即调用函数,区别在于参数传递方式。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
这里 baz 的 this 继承自 bar,而 bar 的 this 是 obj。
三、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
在严格模式下,独立调用函数时,this 是 undefined,而不是 window。
'use strict';
function foo() {
console.log(this);
}
foo(); // 输出 undefined
四、this 的实际开发建议
- 避免 this 混乱:多用箭头函数或
bind明确指定this。 - 对象方法调用:不要轻易把对象方法赋值给变量再调用,容易丢失
this。 - 构造函数和类:用
new创建实例时,记得this指向新对象。 - 面试题多练习:多写代码、多调试,才能真正理解
this的指向。
五、总结
this 是 JavaScript 里最容易让初学者迷惑的知识点之一。它的指向并不是在函数定义时决定的,而是在函数调用时动态绑定的。掌握了 this 的五大绑定规则,再配合实际代码练习,你一定能攻克这个大坑!