this 关键字
什么是 this 关键字
JavaScript 中的this关键字代表当前函数的执行上下文。
this的值依赖于函数的调用方式,它不是静态绑定而是动态绑定的,因此this的值在函数调用时才能确定。
this 的不同场景
全局上下文
在全局执行上下文中(不在任何函数内),this指向全局对象。
在浏览器中,全局对象是window对象;在 Node.js 中,全局对象是global对象。
WARNING
只有在非严格模式下,全局上下文中的this才指向全局对象;在严格模式下,全局上下文中的this是undefined。
函数上下文
在函数上下文中,this的值取决于函数的调用方式。
普通函数调用
在非严格模式下,普通函数调用时,this指向全局对象;在严格模式下,this是undefined。
js
function show() {
console.log(this);
}
show();方法调用
在对象方法中,this指向调用方法的对象。
js
var obj = {
name: "Tom",
show: function () {
console.log(this.name);
},
};
obj.show(); // 输出 'Tom'构造函数调用
在构造函数中,this指向新创建的对象。
js
function Person(name) {
this.name = name;
}
var person = new Person("Alice");
console.log(person.name); // 输出 'Alice'箭头函数
箭头函数不绑定自己的this,无论它如何被调用,它都会捕获所在上下文的this值作为自己的this值。
js
const obj = {
name: "Tom",
show: () => {
console.log(this.name);
},
};
obj.show(); // 在浏览器中输出 undefined,因为箭头函数内部的 this 指向全局对象通过call、apply和bind显示设置this
通过 call、apply 和 bind 方法,可以改变函数的执行上下文。
定义 Person 类用于演示 call、apply 和 bind 方法:
ts
class Person {
name = "Anonymous";
showDetails(age: number, interest: string) {
return `${this.name} is ${age} years old and interested in ${interest}.`;
}
}call
call 第一个参数指定函数的执行上下文(this),剩余的参数是函数的参数。
call 方法会立即调用函数,且只临时改变函数的执行上下文。
ts
const alice = { name: "Alice" };
const resOfCall = Person.prototype.showDetails.call(alice, 25, "JavaScript");
console.log(resOfCall); // Alice is 25 years old and interested in JavaScript.apply
apply 方法第一个参数指定函数的执行上下文(this),第二个参数是一个数组,数组中的元素是函数的参数。
apply 方法会立即调用函数,且只临时改变函数的执行上下文。
ts
const tom = { name: "Tom" };
const resOfApply = Person.prototype.showDetails.apply(tom, [18, "Java"]);
console.log(resOfApply); // Tom is 18 years old and interested in Java.bind
bind 方法接收一个参数,即函数的执行上下文(this),返回一个新函数。
bind 方法不会立即调用函数,而是返回一个永久改变函数的执行上下文的新函数,可以在稍后调用。
ts
const bob = { name: "Bob" };
const showDetails = Person.prototype.showDetails.bind(bob);
const resOfBind = showDetails(30, "TypeScript");
console.log(resOfBind); // Bob is 30 years old and interested in TypeScript.call、apply 和 bind 的区别
call和apply方法会立即调用函数,而bind方法会返回一个新函数,可以在稍后调用。call和apply方法的区别在于参数的传递方式,call方法的参数是逐个传递的,apply方法的参数是数组传递的。