详解JS call() apply()和bind() this的用法区别
作者:admin 时间:2022-5-7 13:16:4 浏览:在前文,非常详细的介绍了JS里this的上下文对象及用法,知道了this
是由其上下文决定的——它是全局的、在对象中、在构造函数或类中、或在 DOM 事件处理程序上,它是隐式引用的。但是,如果使用call
、apply
或bind
方法,你可以明确确定this
应该引用什么。
何时使用call、apply或bind?
何时使用call
、apply
或bind
,取决于程序的上下文。bind
当你想使用事件来访问另一个类中的一个类的属性时,它会特别有用。例如,如果你要编写一个简单的游戏,你可能会将用户界面和 I/O 分离到一个类中,而将游戏逻辑和状态分离到另一个类中。由于游戏逻辑需要访问输入,例如按键和单击,你可能希望bind
事件访问游戏逻辑类的this
值。
重要的部分是知道如何确定this
所指的对象,你可以像前文JS里this的上下文对象及用法介绍的那样,隐含地执行此操作,或者使用接下来将学习的三种方法显式地执行此操作。
call和apply的相同之处
call
和apply
非常相似——它们调用具有指定this
上下文和可选参数的函数。call
和apply
之间的唯一区别是,call
需要一个接一个地传递参数,而apply
将参数作为一个数组。
在此示例中,我们将创建一个对象,并创建一个引用this
但没有this
上下文的函数。
const webkaka = {
name: '卡卡网',
domainName: 'webkaka.com',
}
function describe() {
console.log(`${this.name} 的域名是 ${this.domainName}.`)
}
describe()
输出
"undefined 的域名是 undefined"
由于describe
并且webkaka
没有关联,因此单独调用describe
只会打印 undefined
,因为它正在寻找全局对象上的那些属性。
但是,你可以使用call
和apply
调用函数webkaka
的this
上下文。
describe.call(webkaka)
// or:
describe.apply(webkaka)
输出
"卡卡网 的域名是 webkaka.com"
当这些方法被应用,在describe
和webkaka
之间会有一个新的联系,现在让我们确认this
到底是什么。
function printThis() {
console.log(this)
}
printThis.call(webkaka)
// or:
printThis.apply(webkaka)
输出
{name: "卡卡网", domainName: "webkaka.com"}
在这种情况下,this
实际上成为作为参数传递的对象。
这是call
和apply
是如何相同的。
call和apply的微妙区别
除了能够将this
上下文作为第一个参数传递之外,还可以传递其他参数。
const webkaka = {
name: '卡卡网',
domainName: 'webkaka.com',
}
function printThis() {
console.log(this)
}
function longDescribe(title, year) {
console.log(`${this.name} 的域名是 ${this.domainName}, 它的标题是 ${title} , 它创建于 ${year} 年。` )
}
longDescribe.call(webkaka, '卡卡测速网', 2009);
你要传递的每个附加值,用call
时,它们都作为一个附加参数发送。
输出
卡卡网 的域名是 webkaka.com, 它的标题是 卡卡测速网 , 它创建于 2009 年。
如果你尝试使用apply
发送完全相同的参数,则会发生以下情况:
longDescribe.apply(webkaka, '卡卡测速网', 2009);
输出
Uncaught TypeError: second argument to Function.prototype.apply must be an array
对于apply
,你必须传递数组中的所有参数。
longDescribe.apply(webkaka, ['卡卡测速网', 2009]);
输出
卡卡网 的域名是 webkaka.com, 它的标题是 卡卡测速网 , 它创建于 2009 年。
单独传递参数或以数组形式传递参数之间的区别是微妙的,但要注意这一点很重要。使用起来apply
可能更简单方便,因为如果某些参数细节发生变化,它不需要更改函数调用。
this与bind方法
call
和apply
都是一次性使用的方法——如果你用this
上下文调用方法,它会拥有它,但原始函数将保持不变。
有时,你可能需要在另一个对象的this
上下文中反复使用一个方法,在这种情况下,你可以使用bind
方法创建一个具有显式绑定this
的全新函数。
const webkaka = {
name: '卡卡网',
domainName: 'webkaka.com',
}
function describe() {
console.log(`${this.name} 的域名是 ${this.domainName}`)
}
const Summary = describe.bind(webkaka);
Summary();
输出
卡卡网 的域名是 webkaka.com
在这个例子中,每次你调用 Summary
,它总是会返回绑定到它的this
原始值。尝试将新this
上下文绑定到它会失败,因此你始终可以相信绑定函数返回你期望的this
值。
const webkaka = {
name: '卡卡网',
domainName: 'webkaka.com',
}
function describe() {
console.log(`${this.name} 的域名是 ${this.domainName}`)
}
const Summary = describe.bind(webkaka);
const webkaka2 = {
name: '卡卡网',
domainName: 'webkaka.com',
}
Summary.bind(webkaka2);
Summary();
输出
卡卡网 的域名是 webkaka.com
尽管此示例尝试Summary
再次绑定,但它保留了第一次绑定时的原始this
上下文。
总结
本文详细介绍了JS里this
与call()
apply()
和bind()
的用法相同及区别,我们在使用时应该明白其中的含义,以免用错方法而得不到期望的结果。
参考文章
- 站长推荐