JavaScript中的call和apply的用途以及区别
发布时间 - 2026-01-10 22:27:24 点击率:次apply 接受两个参数,第一个参数指定了函数体内this 对象的指向,第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组,apply 方法把这个集合中的元素作为参数传递给被调用的函数:
var func = function( a, b, c ){
alert ( [ a, b, c ] ); // 输出 [ 1, 2, 3 ]
};
func.apply( null, [ 1, 2, 3 ] );
在这段代码中,参数 1、2、3 被放在数组中一起传入func函数,它们分别对应func参数列表中的a、b、c。
call 传入的参数数量不固定,跟apply 相同的是,第一个参数也是代表函数体内的this 指向,从第二个参数开始往后,每个参数被依次传入函数:
var func = function( a, b, c ){
alert ( [ a, b, c ] ); // 输出 [ 1, 2, 3 ]
};
func.call( null, 1, 2, 3 );
当调用一个函数时,JavaScript 的解释器并不会计较形参和实参在数量、类型以及顺序上的区别,JavaScript 的参数在内部就是用一个数组来表示的。从这个意义上说,apply比call的使用率更高,我们不必关心具体有多少参数被传入函数,只要用apply 一股脑地推过去就可以了。call是包装在apply上面的一颗语法糖,如果我们明确地知道函数接受多少个参数,而且想一目了然地表达形参和实参的对应关系,那么也可以用call 来传送参数。
call和apply的用途
1. 改变this 指向
call 和apply 最常见的用途是改变函数内部的this 指向,我们来看个例子:
var obj1 = {
name: 'sven'
};
var obj2 = {
name: 'anne'
};
window.name = 'window';
var getName = function(){
alert ( this.name );
};
getName(); // 输出: window
getName.call( obj1 ); // 输出: sven
getName.call( obj2 ); // 输出: anne
当执行getName.call( obj1 )这句代码时,getName 函数体内的this 就指向obj1 对象,所以此处的
var getName = function(){
alert ( this.name );
};
实际上相当于:
var getName = function(){
alert ( obj1.name ); // 输出: sven
};
在实际开发中,经常会遇到this指向被不经意改变的场景,比如有一个div节点,div节点的onclick 事件中的this 本来是指向这个div的:
document.getElementById( 'div1' ).onclick = function(){
alert( this.id ); // 输出:div1
};
假如该事件函数中有一个内部函数func,在事件内部调用func 函数时,func 函数体内的this就指向了window,而不是我们预期的div,见如下代码:
document.getElementById( 'div1' ).onclick = function(){
alert( this.id ); // 输出:div1
var func = function(){
alert ( this.id ); // 输出:undefined
}
func();
};
这时候我们用call 来修正func 函数内的this,使其依然指向div:
document.getElementById( 'div1' ).onclick = function(){
var func = function(){
alert ( this.id ); // 输出:div1
}
func.call( this );
};
2. Function.prototype.bind
大部分高级浏览器都实现了内置的Function.prototype.bind,用来指定函数内部的this 指向,即使没有原生的Function.prototype.bind 实现,我们来模拟一个也不是难事,代码如下:
Function.prototype.bind = function( context ){
var self = this; // 保存原函数
return function(){ // 返回一个新的函数
return self.apply( context, arguments ); // 执行新的函数的时候,会 把之前传入的context
// 当作新函数体内的this
}
};
var obj = {
name: 'sven'
};
var func = function(){
alert ( this.name ); // 输出:sven
}.bind( obj);
func();
我们通过Function.prototype.bind 来“包装”func 函数,并且传入一个对象context 当作参数,这个context 对象就是我们想修正的this 对象。
在Function.prototype.bind 的内部实现中,我们先把func 函数的引用保存起来,然后返回一个新的函数。当我们在将来执行func 函数时,实际上先执行的是这个刚刚返回的新函数。在新函数内部,self.apply( context, arguments )这句代码才是执行原来的func 函数,并且指定context对象为func 函数体内的this。
这是一个简化版的Function.prototype.bind 实现,通常我们还会把它实现得稍微复杂一点,
使得可以往func 函数中预先填入一些参数:
Function.prototype.bind = function(){
var self = this, // 保存原函数
context = [].shift.call( arguments ), // 需要绑定的this 上下文
args = [].slice.call( arguments ); // 剩余的参数转成数组
return function(){ // 返回一个新的函数
return self.apply( context, [].concat.call( args, [].slice.call( arguments ) ) );
// 执行新的函数的时候,会把之前传入的context 当作新函数体内的this
// 并且组合两次分别传入的参数,作为新函数的参数
}
};
var obj = {
name: 'sven'
};
var func = function( a, b, c, d ){
alert ( this.name ); // 输出:sven
alert ( [ a, b, c, d ] ) // 输出:[ 1, 2, 3, 4 ]
}.bind( obj, 1, 2 );
func( 3, 4 );
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
# call
# apply
# 区别
# javascript中apply和call方法的作用及区别说明
# js apply/call/caller/callee/bind使用方法与区别分析
# JavaScript学习点滴 call、apply的区别
# JavaScript中apply与call的用法意义及区别说明
# 在JavaScript中call()与apply()区别
# JavaScript中的this
# apply使用及区别详解
# 理解Javascript的caller
# callee
# apply区别
# 深入理解JavaScript中的call、apply、bind方法的区别
# javascript中apply、call和bind的使用区别
# Javascript call和apply区别及使用方法
# 深入理解关于javascript中apply()和call()方法的区别
# JavaScript中call和apply方法的区别实例分析
# 体内
# 的是
# 第一个
# 第二个
# 这句
# 放在
# 作新
# 才是
# 还会
# 可以用
# 中有
# 两次
# 把它
# 一颗
# 也可
# 这段
# 这是一个
# 有多少
# 更高
# 使其
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
英语简历制作免费网站推荐,如何将简历翻译成英文?
laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程
Laravel 419 page expired怎么解决_Laravel CSRF令牌过期处理
Python文件操作最佳实践_稳定性说明【指导】
怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?
iOS中将个别页面强制横屏其他页面竖屏
怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?
网站图片在线制作软件,怎么在图片上做链接?
如何用IIS7快速搭建并优化网站站点?
如何在万网自助建站平台快速创建网站?
Python制作简易注册登录系统
Win11怎样安装网易有道词典_Win11安装词典教程【步骤】
高端建站三要素:定制模板、企业官网与响应式设计优化
Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】
如何确保FTP站点访问权限与数据传输安全?
HTML5空格在Angular项目里怎么处理_Angular中空格的渲染问题【详解】
浅谈Javascript中的Label语句
如何基于云服务器快速搭建网站及云盘系统?
如何在阿里云高效完成企业建站全流程?
零基础网站服务器架设实战:轻量应用与域名解析配置指南
Laravel如何实现文件上传和存储?(本地与S3配置)
如何获取PHP WAP自助建站系统源码?
如何利用DOS批处理实现定时关机操作详解
Laravel怎么生成URL_Laravel路由命名与URL生成函数详解
什么是JavaScript解构赋值_解构赋值有哪些实用技巧
微信小程序 HTTPS报错整理常见问题及解决方案
laravel怎么配置和使用PHP-FPM来优化性能_laravel PHP-FPM配置与性能优化方法
如何用VPS主机快速搭建个人网站?
高端企业智能建站程序:SEO优化与响应式模板定制开发
如何快速辨别茅台真假?关键步骤解析
高防服务器如何保障网站安全无虞?
Laravel怎么做数据加密_Laravel内置Crypt门面的加密与解密功能
进行网站优化必须要坚持的四大原则
零服务器AI建站解决方案:快速部署与云端平台低成本实践
网站制作大概要多少钱一个,做一个平台网站大概多少钱?
Laravel如何使用Service Container和依赖注入?(代码示例)
Laravel的路由模型绑定怎么用_Laravel Route Model Binding简化控制器逻辑
高防服务器租用如何选择配置与防御等级?
网页设计与网站制作内容,怎样注册网站?
Laravel怎么连接多个数据库_Laravel多数据库连接配置
Laravel Seeder填充数据教程_Laravel模型工厂Factory使用
Python文件流缓冲机制_IO性能解析【教程】
Laravel如何实现API版本控制_Laravel API版本化路由设计策略
如何在IIS中新建站点并配置端口与IP地址?
Laravel如何编写单元测试和功能测试?(PHPUnit示例)
Java垃圾回收器的方法和原理总结
Laravel如何集成Inertia.js与Vue/React?(安装配置)
个人摄影网站制作流程,摄影爱好者都去什么网站?
Laravel如何操作JSON类型的数据库字段?(Eloquent示例)
WEB开发之注册页面验证码倒计时代码的实现

