1. this 是什么?
在 JavaScript 中,this 关键字用于指向调用它的对象。但它的指向并不是在编写代码时确定的,而是在 函数执行时 决定的。
2. this 在不同场景下的表现
2.1 作为对象的方法调用
javascript
const obj = {
name: 'Tom',
sayHello() {
console.log(this.name);
}
};
obj.sayHello(); // Tom
解析 : this 指向 obj,因为 sayHello 是通过 obj 调用的。
2.2 直接调用函数(普通函数调用)
scss
function show() {
console.log(this);
}
show(); // 非严格模式下:window / 严格模式下:undefined
解析:
- 在非严格模式 下,
this指向全局对象window。 - 在严格模式 下,
this为undefined。
2.3 构造函数调用
ini
function Person(name) {
this.name = name;
}
const p = new Person('Tom');
console.log(p.name); // Tom
解析 : this 指向新创建的实例 p。
2.4 箭头函数中的 this
javascript
const obj = {
name: 'Tom',
sayHello: () => {
console.log(this.name);
}
};
obj.sayHello(); // undefined
解析:
- 箭头函数不会创建自己的
this,它的this继承自定义它的作用域。 - 这里
this指向的是全局对象window(在严格模式下undefined)。
正确写法(使用普通函数):
javascript
const obj = {
name: 'Tom',
sayHello() {
console.log(this.name);
}
};
obj.sayHello(); // Tom
2.5 this 丢失问题
javascript
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(this.name);
}
}
const p = new Person('Tom');
const x = p.sayHello;
x(); // undefined
原因 : p.sayHello 只是一个函数的引用 ,它被赋值给变量 x,但 x 和 p 没有任何关系了 。 在 JavaScript 中,this 只在函数被调用时确定,而不是在函数定义时。
所以这里this 指向 window(非严格模式)或 undefined(严格模式),
解决方案:
-
使用
bind绑定thisiniconst x = p.sayHello.bind(p); x(); // Tom -
使用箭头函数 (继承
this)scssconst x = () => p.sayHello(); x(); // Tom -
使用
call或applyscssx.call(p); // Tom x.apply(p); // Tom
3. this 在事件处理程序中
javascript
document.querySelector("button").addEventListener("click", function() {
console.log(this); // this 指向被点击的 button 元素
});
注意 :如果使用箭头函数,this 可能会指向 window 而不是按钮。
javascript
document.querySelector("button").addEventListener("click", () => {
console.log(this); // this 指向 window,而不是按钮
});
解决方案:用普通函数代替箭头函数。
4. this 在 setTimeout 和 setInterval 中
javascript
const obj = {
name: 'Tom',
sayHello() {
setTimeout(function() {
console.log(this.name);
}, 1000);
}
};
obj.sayHello(); // undefined
原因 :setTimeout 里的 this 指向 window(非严格模式)。
解决方案:
-
使用箭头函数 (继承
this)javascriptsayHello() { setTimeout(() => { console.log(this.name); }, 1000); }
5. this 在 call、apply 和 bind 中
call 和 apply (手动绑定 this 并立即执行)
arduino
function sayHello() {
console.log(this.name);
}
const person = { name: 'Tom' };
sayHello.call(person); // Tom
sayHello.apply(person); // Tom
区别:
call(thisArg, arg1, arg2, ...)直接传参数。apply(thisArg, [arg1, arg2, ...])以数组方式传参数。
bind (手动绑定 this ,但不会立即执行)
ini
const boundFunc = sayHello.bind(person);
boundFunc(); // Tom
6. 总结
| 场景 | this 指向 |
|---|---|
| 对象方法调用 | 调用它的对象 |
| 普通函数调用 | window(非严格模式)或 undefined(严格模式) |
| 构造函数调用 | 新创建的实例 |
| 箭头函数 | 继承外层作用域的 this |
| 事件处理程序 | 绑定的 DOM 元素(普通函数)或 window(箭头函数) |
setTimeout/setInterval |
window(非严格模式)或 undefined(严格模式) |
call/apply/bind |
绑定的对象 |
注意
- 箭头函数不会创建自己的
this,它会继承定义它的作用域的this。 - 普通函数的
this取决于调用方式,而不是定义位置。 - 手动绑定
this可以用bind,call,apply。