javascript中call,apply,bind的用法对比分析


Posted in Javascript onFebruary 12, 2015

关于call,apply,bind这三个函数的用法,是学习javascript这门语言无法越过的知识点。下边我就来好好总结一下它们三者各自的用法,及常见的应用场景。

首先看call这个函数,可以理解成"借用“,"请求"。想像一下如下的情景:你孤单一人漂泊在外,有急事想往家里打电话,可是很不巧,手机欠费了,或者没电了,或者掉坑里了,总之你的手机就是用不成。可是你非打这个电话不可,于是你可以去借一下朋友的手机,或者借用一下邻居的手机,或者公用电话,这样呢,你就可以在自己没有手机可用的情况下,完成打电话这个事情,而至于你是用谁的电话打的,就不重要了,反正和用你自己的手机打的电话是一样的效果。call这个函数的初衷也和这个类似,下面我用代码来模拟一下它的应用情景:

var frog = {
    name : 'frog',
    say : function(){
      alert(this.name);
    }
  }
  var rabbit = {
    name : 'rabbit'
  }
  frog.say.call(rubbit) // rabbit

rubbit这个对象是个哑吧,但是他想要说出自己的名字,光凭它自己的能力,是不可能实现的,好在呢,它有一个叫frog的好基友,它可以说话。于是呢,rubbit就请求frog替它实现这个心愿。frog.say.call()的第一个参数,一定是要填写发出请求的人,律师喜欢称为委托人。这里是rubbit请求frog替它say名字,所以填写rubbit。这样一来,在say的时候,就会查找rubbit的name,而不是frog的name了。如果这里填写frog会是什么样子呢?这就好比是自己请求自己做某事,喂自己代盐也是可以的。可以试一下:

var frog = {
    name : 'frog',
    say : function(){
      alert(this.name);
    }
  }
  var rabbit = {
    name : 'rabbit'
  }
  frog.say.call(frog) // frog

自己喂自己袋盐,肯定是说自己的名字啦,这完全没有什么意外的。下面我们来看看call的经典用法:

//把参数转化成真正的数组对象
function frog(){
  var arr = [].slice.call(arguments);
  console.log(arguments.slice,arr.slice)
    // undefined function slice() { [native code] }
}
  frog(1,2,3,4)

能过这么一call,我们就可以把arguments对象当成数组对象来使用了。关于call的用法很多,翻开jquery的源码,很容易就能找到很多运用的地方。在此不一一列举了,还是回到我们前面的情景,借电话这种事太简单了,打完电话,肯定还想捎点什么东西回去,毕竟这么多年漂泊在外,没有好好孝敬下老人,买点当地的特产回去,肯定是极好的。可是外边的生活压力是如此之大,每天除了上班还要加班,如果请假的话,不但工资要扣,还要花费不少的路费,这些钱加起来,估计都够老人在家里一年的用度了。想想不划算,于是又想到call这个函数,请它帮忙,顺道带回去是非常明智的选择,而且它不收费,不限量,不限重,有多少,带多少。我再次用代码来演示一下:

var frog = {
    name : 'frog',
    send : function(money,food,milk,suagate){
      alert(money+food+milk+suagate);
    }
  }
  var rabbit = {
    name : 'rabbit'
  }
  frog.send.call(rubbit,'money','food','milk','suagate')

如果你有钱任性,甚至可以把iphone6 plus什么的也寄几个回去。.^_^.

说到这里call就差不多结束了,我也不知道上面的情景剧,是不是让你明白了call是怎么回事,如果只是勾起了你的思乡之情,那我表示抱歉。

call还有一个同父异母的兄弟,叫apply,如果弄明白了call的用法,那么apply其实也是一回事,唯一的区别呢,就是apply不喜欢传东西的时候,一个东西打一个包,显得很麻烦不说,还不环保。于是他就提供一个装东西的大箱子,你把你要传的东西全放在它提供的箱子里就好了。这个大箱子,就是一个数组。上面的例子,用apply来做的话,就是这样子的:

var frog = {
    name : 'frog',
    send : function(money,food,milk,suagate){
      alert(money+food+milk+suagate);
    }
  }
  var rabbit = {
    name : 'rabbit'
  }







//注意参数的区别
  frog.send.apply(rubbit,['money','food','milk','suagate'])

以上就是apply,call的前世今生了。可是万万没想到,apply和call的爸爸,前些年搞房地产发了财,在外边还有一个叫bind 的私生子。虽然比call和apply这两个哥哥晚出道几年,但是能力也不容小视。只不过,他的身份,在某些地方,是不承认的。比如IE6。下面我还是用代码来演示下他的本领:

var name = 'rubbit';
  var frog = {
    name : 'frog',
    say : function(){
      setTimeout(function(money,milk){
        alert(this.name+money+milk)
      }.bind(this,'money','milk'),1000)
    }
  }
  frog.say();

通过对比发现,bind可以直接连在function(){}后面用。相当于把call 和 apply 都省了,直接在函数后面指定委托人和要传递的参数。从传参的风格上来说,更像call一些。

关于bind ,我们再来看一段经典的用法:

var obj = {
  name : 'frog'
}
document.addEventListener('click',function(){
  alert(this.name); // frog
}.bind(obj),false);

总结一下,apply,call,bind,这三兄弟的相同点是:

 1. 第一个参数都是邦定作用域,即是在谁的地盘上做事。

 2. 都可以传递参数

不同点是:

  apply,call 兼容性更好,bind某些低版本的浏览器不支持。

  apply 传递的参数必须是用数组进行包装的,而 call 和 bind 则是将要传递的参数一一列出。

大家是否对call,apply,bind三个函数的用法有了更深入的认识了呢,希望本文能对大家有所帮助。

Javascript 相关文章推荐
Prototype String对象 学习
Jul 19 Javascript
jQuery插件 tabBox实现代码
Feb 09 Javascript
Extjs4 类的定义和扩展实例
Jun 28 Javascript
jQuery结合CSS制作漂亮的select下拉菜单
May 03 Javascript
javascript日期格式化方法小结
Dec 17 Javascript
javascript拖拽应用实例
Mar 25 Javascript
vue+axios实现登录拦截的实例代码
May 22 Javascript
JavaScript学习笔记之DOM操作实例分析
Jan 08 Javascript
详解vue 图片上传功能
Apr 30 Javascript
微信小程序文字显示换行问题
Jul 28 Javascript
javascript实现切割轮播效果
Nov 28 Javascript
Javascript中的奇葩知识,你知道吗?
Jan 25 Javascript
javascript手工制作悬浮菜单
Feb 12 #Javascript
jquery+javascript编写国籍控件
Feb 12 #Javascript
JS实现的生成随机数的4个函数分享
Feb 11 #Javascript
JavaScript中的分号插入机制详细介绍
Feb 11 #Javascript
Javascript核心读书有感之语句
Feb 11 #Javascript
JavaScript数据结构和算法之二叉树详解
Feb 11 #Javascript
JavaScript中的函数模式详解
Feb 11 #Javascript
You might like
如何冲泡挂耳包咖啡?技巧是什么
2021/03/04 冲泡冲煮
详解PHP实现执行定时任务
2015/12/21 PHP
php 使用mpdf实现指定字段配置字体样式的方法
2019/07/29 PHP
js跨域问题之跨域iframe自适应大小实现代码
2010/07/17 Javascript
关于JAVASCRIPT urldecode URL解码的问题
2012/01/08 Javascript
图片延迟加载的实现代码(模仿懒惰)
2013/03/29 Javascript
用js调用迅雷下载代码的二种方法
2013/04/15 Javascript
JQEasy-ui在IE9以下版本中二次加载的问题分析及处理方法
2014/06/23 Javascript
AngularJS基础 ng-repeat 指令简单示例
2016/08/03 Javascript
JS与jQuery实现隔行变色的方法
2016/09/09 Javascript
Bootstrap Table使用心得总结
2016/11/29 Javascript
jQueryUI 拖放排序遇到滚动条时有可能无法执行排序的小bug及解决方案
2016/12/19 Javascript
使用JS在浏览器中判断当前网络连接状态的几种方法
2017/05/05 Javascript
深入理解Webpack 中路径的配置
2017/06/17 Javascript
jQuery实现表格冻结顶栏效果
2017/08/20 jQuery
Cropper.js 实现裁剪图片并上传(PC端)
2017/08/20 Javascript
简单的vuex 的使用案例笔记
2018/04/13 Javascript
浅谈vue项目如何打包扔向服务器
2018/05/08 Javascript
使用 Angular RouteReuseStrategy 缓存(路由)组件的实例代码
2019/11/01 Javascript
JavaScript 浏览器对象模型BOM原理与常见用法实例分析
2019/12/16 Javascript
[05:15]2018年度CS GO社区贡献奖-完美盛典
2018/12/16 DOTA
python cx_Oracle的基础使用方法(连接和增删改查)
2017/11/19 Python
Python cookbook(数据结构与算法)找出序列中出现次数最多的元素算法示例
2018/03/15 Python
Python求两个圆的交点坐标或三个圆的交点坐标方法
2018/11/07 Python
简单了解django orm中介模型
2019/07/30 Python
python中有函数重载吗
2020/05/28 Python
Python中logging日志记录到文件及自动分割的操作代码
2020/08/05 Python
纯css3(无图片/js)制作的几个社交媒体网站的图标
2013/03/21 HTML / CSS
html+css实现自定义图片上传按钮功能
2019/09/04 HTML / CSS
英国时尚服饰电商:Boohoo
2017/10/12 全球购物
澳大利亚新奇小玩意网站:Yellow Octopus
2017/12/28 全球购物
调研座谈会发言材料
2014/08/23 职场文书
结婚当天新郎保证书
2015/05/08 职场文书
Oracle 区块链表创建过程详解
2021/05/15 Oracle
深入浅析python3 依赖倒置原则(示例代码)
2021/07/09 Python
Python实现猜拳与猜数字游戏的方法详解
2022/04/06 Python