JavaScript中的this
this是JavaScript中一个特殊关键字,用于指代当前执行上下文中的对象。它的难以理解之处就是值不是固定的,是再函数被调用时根据调用场景动态确定的,主要根据函数的调用方式来决定this指向的对象。this 的值在函数被调用时动态确定,以下是几种常见的情况:
-
全局上下文中:
当在全局作用域中调用函数时,this指向全局对象。在浏览器环境中,这个全局对象是window对象。console.log(this); // 在浏览器中,输出为 Window 对象 -
函数作为对象的方法:
当函数作为对象的方法被调用时,this指向调用该方法的对象。const obj = { property: 'value', printProperty: function() { console.log(this.property); } }; obj.printProperty(); // 输出 'value' -
构造函数中:
在使用new关键字创建实例时,构造函数内部的this指向即将创建的新实例。function Person(name) { this.name = name; } const person = new Person('Alice'); console.log(person.name); // 输出 'Alice' -
显式绑定:
使用call、apply、bind方法可以显式指定this的绑定对象。
function greet(message) {
console.log(`${message}, ${this.name}!`);
}
const person = { name: 'Bob' };
greet.call(person, 'Hello'); // 输出 'Hello, Bob!'
- 箭头函数:
箭头函数不绑定this,它会捕获外层作用域的this值作为自己的this。
const obj = {
method: function() {
const arrowFunc = () => {
console.log(this === obj);
};
arrowFunc();
}
};
obj.method(); // 输出 true
- class中的this:
类中的this默认指向类的实例对象。
class Rectangle {
constructor(width, height) {
this.width = width;
this.height = height;
}
}
const rect = new Rectangle(10, 20);
console.log(rect.width); // 输出 10
- 事件绑定
事件绑定中的this是指向触发事件的dom元素。
const button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log(this === button);
});
// 在按钮点击时输出 true
如何改变this指向
改变 this 指向是在 JavaScript 中常见的需求,特别是当你想要在不同的上下文中调用函数时。以下是几种常见的方法来改变 this 指向:
-
使用
call方法:
call方法允许你显式地指定函数内部的this值,并且传递参数列表。第一个参数是要绑定的this值,后面的参数是函数的参数。function greet(message) { console.log(`${message}, ${this.name}!`); } const person = { name: 'Alice' }; greet.call(person, 'Hello'); // 输出 'Hello, Alice!' 这里把this绑定给person对象 -
使用
apply方法:
apply方法与call类似,但它接受一个数组或类数组对象作为参数,其中的元素将作为函数参数传递。function greet(message) { console.log(`${message}, ${this.name}!`); } const person = { name: 'Bob' }; greet.apply(person, ['Hi']); // 输出 'Hi, Bob!' -
使用
bind方法:
bind方法创建一个新函数,将this值永久地绑定,并可以预先设置部分参数。原函数不会受到影响。function greet(message) { console.log(`${message}, ${this.name}!`); } const person = { name: 'Charlie' }; const greetPerson = greet.bind(person); greetPerson('Hey'); // 输出 'Hey, Charlie!' -
使用箭头函数:
箭头函数不会绑定独立的this值,而是捕获其外部函数的this值。const obj = { method: function() { const arrowFunc = () => { console.log(this === obj); }; arrowFunc(); } }; obj.method(); // 输出 true
call和apply区别
-
bind方法:bind方法创建一个新函数,将原函数的this值永久绑定到指定的对象,并可以在调用时传递参数。- 它不会立即执行原函数,而是返回一个新的函数,需要手动调用新函数以执行原函数。
bind方法不会改变原函数的上下文,而是返回一个新函数。
-
call方法:call方法立即调用函数,并指定函数内部的this值,同时可以传递参数列表。- 它的第一个参数是要绑定的
this值,后续的参数会作为函数的参数传递。
-
apply方法:apply方法也立即调用函数,并指定函数内部的this值,但参数传递方式不同。- 它的第一个参数是要绑定的
this值,第二个参数是一个数组(或类数组对象),其中的元素会作为函数的参数传递。
实现call、apply、bind
这里实现简化版的,核心思路是:
- 将函数设为传入对象的一个属性
- 执行该函数
- 删除该函数(临时函数调用完成删除,防止内存泄漏,以免context 对象造成污染)
- 返回结果或传入的this
call
Function.prototype.myCall = function(context, ...args) {
context = context || window;
const fn = Symbol();
context[fn] = this;
const result = context[fn](...args);
delete context[fn];
return result;
}
apply
Function.prototype.myApply = function(context, args) {
context = context || window;
const fn = Symbol();
context[fn] = this;
let result;
if(args) {
result = context[fn](...args);
} else {
result = context[fn]();
}
delete context[fn];
return result;
}
bind
Function.prototype.myBind = function(context, ...outerArgs) {
context = context || window;
const _this = this;
return function(...innerArgs) {
context[fn] = _this;
const result = context[fn](...outerArgs, ...innerArgs);
delete context[fn];
return result;
}
}
本文详细解释了JavaScript中this的关键特性,包括其在全局、对象方法、构造函数、显式绑定、箭头函数和类中的行为,以及如何通过call、apply和bind等方法改变this的指向。
2049

被折叠的 条评论
为什么被折叠?



