前言
JavaScript 中的函数是一个对象,它可以有自己的属性和方法,也可以通过调用来执行一段代码。在调用函数时,函数的上下文即 this
值会被自动设置为函数的调用者。但是,在某些情况下,我们希望能够手动改变函数的上下文,这时候就可以使用 call
、apply
或 bind
方法。
如何使用 & 区别
call
, apply
, bind
都可以用来更改函数执行时的上下文对象(即 this
的值)。它们的区别在于传递参数的方式和返回结果的不同。
call
和 apply
用法类似,第一个参数是要指定的上下文对象,之后的参数是传递给函数的参数列表。它们的区别在于传递参数的方式,call
是依次列出参数,apply
则是把参数放在数组中传递。
bind
则是返回一个新的函数,把指定的上下文对象和参数绑定到原函数上,这个新函数可以在后面任意时刻调用,调用时 this
的值和绑定的上下文对象一致。
举个例子
// call 示例
const person = {
name: 'Allen',
greet: function (age) {
console.log(`Hello, my name is ${this.name} and I'm ${age} years old.`);
}
};
const cat = {
name: 'damao'
};
person.greet.call(cat, 5); // 输出 "Hello, my name is damao and I'm 5 years old."
// apply 示例
const dog = {
name: 'wong'
};
person.greet.apply(dog, [7]); // 输出 "Hello, my name is wong and I'm 7 years old."
// bind 示例
const boundFunction = person.greet.bind(cat, 3);
boundFunction(); // 输出 "Hello, my name is damao and I'm 3 years old."
在这个例子中,person
对象有一个 greet
方法,用来输出自我介绍的语句。call
和 apply
都是在 cat
和 dog
对象上调用 greet
方法,以修改 this
的值。而 bind
则是将 cat
对象和一个 age
参数绑定到 person.greet
上,生成一个新的函数 boundFunction
,随后调用该函数以输出相应的语句。
何时使用
- 需要显式地绑定this对象;(文中已经有示例了)
- 在将函数作为参数传递给另一个函数时,需要将上下文从一个对象更改为另一个对象;
在这个例子中,我们有两个对象:function printAge() { console.log(this.age); } const person = { name: 'Allen', age: 30 }; const anotherPerson = { name: 'Celia', age: 25 }; function callAndPrintAge(fn) { fn.call(this); } callAndPrintAge.call(anotherPerson, printAge); // 25
person
和anotherPerson
,以及一个printAge
函数。我们创建了一个名为callAndPrintAge
的函数,它接受一个函数作为参数,并将它的上下文设置为第一个参数(使用call
方法)。我们调用callAndPrintAge
,并将它的上下文设置为anotherPerson
对象,以便我们可以从另一个对象中打印年龄。 - 当需要调用一个类似数组的对象上的函数时,可以使用apply方法来避免编写重复的代码。
这个例子中,我们有一个类似数组的对象,它有3个属性:0、1和2,以及一个长度为3的length属性。我们使用const arrayLikeObject = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 }; Array.prototype.join.apply(arrayLikeObject, ['|']); // 'foo|bar|baz'
apply()
方法在类似数组的对象上调用数组的join()
方法,将参数作为数组传递。由于我们不能直接调用类似数组的对象上的join()
方法,所以我们使用apply方法来绕过这个问题,这样我们就可以像在数组上一样调用这个方法了。