技术频道导航
HTML/CSS
.NET技术
IIS技术
PHP技术
Js/JQuery
Photoshop
Fireworks
服务器技术
操作系统
网站运营

赞助商

分类目录

赞助商

最新文章

搜索

详解JS call() apply()和bind() this的用法区别

作者:admin    时间:2022-5-7 13:16:4    浏览:

在前文,非常详细的介绍了JS里this的上下文对象及用法,知道了this是由其上下文决定的——它是全局的、在对象中、在构造函数或类中、或在 DOM 事件处理程序上,它是隐式引用的。但是,如果使用callapplybind方法,你可以明确确定this应该引用什么。

详解JS里this在call() apply()和bind()的用法区别

何时使用call、apply或bind?

何时使用callapplybind,取决于程序的上下文。bind当你想使用事件来访问另一个类中的一个类的属性时,它会特别有用。例如,如果你要编写一个简单的游戏,你可能会将用户界面和 I/O 分离到一个类中,而将游戏逻辑和状态分离到另一个类中。由于游戏逻辑需要访问输入,例如按键和单击,你可能希望bind事件访问游戏逻辑类的this值。

重要的部分是知道如何确定this所指的对象,你可以像前文JS里this的上下文对象及用法介绍的那样,隐含地执行此操作,或者使用接下来将学习的三种方法显式地执行此操作。

call和apply的相同之处

callapply非常相似——它们调用具有指定this上下文和可选参数的函数。callapply之间的唯一区别是,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,因为它正在寻找全局对象上的那些属性。

但是,你可以使用callapply调用函数webkakathis上下文。

describe.call(webkaka)
// or:
describe.apply(webkaka)

输出

"卡卡网 的域名是 webkaka.com"

当这些方法被应用,在describewebkaka之间会有一个新的联系,现在让我们确认this到底是什么。

function printThis() {
console.log(this)
}
printThis.call(webkaka)
// or:
printThis.apply(webkaka)

输出

{name: "卡卡网", domainName: "webkaka.com"}

 

在这种情况下,this实际上成为作为参数传递的对象。

这是callapply是如何相同的。

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方法

callapply都是一次性使用的方法——如果你用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里thiscall() apply()bind()的用法相同及区别,我们在使用时应该明白其中的含义,以免用错方法而得不到期望的结果。

参考文章

标签: this  call方法  apply方法  bind方法  
x
x
  • 站长推荐