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 相关文章推荐
[原创]用javascript实现检测指定目录是否存在的方法
Jan 12 Javascript
jQuery UI Autocomplete 体验分享
Feb 14 Javascript
JS中的this变量的使用介绍
Oct 21 Javascript
js判断客户端是iOS还是Android等移动终端的方法
Dec 11 Javascript
AngularJS 入门教程之事件处理器详解
Aug 19 Javascript
JavaScript代码里的判断小结
Aug 22 Javascript
基于MVC+EasyUI的web开发框架之使用云打印控件C-Lodop打印页面或套打报关运单信息
Aug 29 Javascript
原生javascript上传图片带进度条【实例分享】
Apr 06 Javascript
ES6 迭代器(Iterator)和 for.of循环使用方法学习(总结)
Feb 08 Javascript
vue-cli项目修改文件热重载失效的解决方法
Sep 19 Javascript
微信小程序实现复选框效果
Dec 28 Javascript
详解如何实现Element树形控件Tree在懒加载模式下的动态更新
Apr 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/06 咖啡文化
《PHP编程最快明白》第二讲 数字、浮点、布尔型、字符串和数组
2010/11/01 PHP
ThinkPHP 模板引擎使用详解
2017/05/07 PHP
php+redis消息队列实现抢购功能
2018/02/08 PHP
thinkPHP5框架实现多数据库连接,跨数据连接查询操作示例
2019/05/29 PHP
JavaScript DOM学习第四章 getElementByTagNames
2010/02/19 Javascript
JavaScript类型转换方法及需要注意的问题小结(挺全面)
2010/11/11 Javascript
jQuery之过滤元素操作小结
2013/11/30 Javascript
javascript 按键事件(兼容各浏览器)
2013/12/20 Javascript
让JavaScript的Alert弹出框失效的方法禁止弹出警告框
2014/09/03 Javascript
js焦点文字滚动效果代码分享
2015/08/25 Javascript
解决nodejs中使用http请求返回值为html时乱码的问题
2017/02/18 NodeJs
js实现简易垂直滚动条
2017/02/22 Javascript
详谈jQuery中的一些正则匹配表达式
2017/03/08 Javascript
浅谈JS 数字和字符串之间相互转化的纠纷
2017/10/20 Javascript
基于vue-ssr的静态网站生成器VuePress 初体验
2018/04/17 Javascript
在vue2.0中引用element-ui组件库的方法
2018/06/21 Javascript
jquery实现垂直无限轮播的方法分析
2019/07/16 jQuery
JavaScript仿京东秒杀倒计时
2020/03/17 Javascript
vue使用vue-quill-editor富文本编辑器且将图片上传到服务器的功能
2021/01/13 Vue.js
python实现识别相似图片小结
2016/02/22 Python
python 将print输出的内容保存到txt文件中
2018/07/17 Python
Python 实现使用空值进行赋值 None
2020/03/12 Python
Python flask框架端口失效解决方案
2020/06/04 Python
css3和jquery实现的可折叠导航菜单适合放在手机网页的导航菜单
2014/09/02 HTML / CSS
CSS3中HSL和HSLA的简单使用示例
2015/07/14 HTML / CSS
Snapfish英国:在线照片打印和个性化照片礼品
2017/01/13 全球购物
Book Depository欧盟:一家领先的国际图书零售商
2019/05/21 全球购物
介绍一下linux的文件系统
2015/10/06 面试题
高中生家长会演讲稿
2014/01/14 职场文书
写给女朋友的检讨书
2014/01/28 职场文书
幼儿园门卫岗位职责范本
2014/07/02 职场文书
深入浅析Redis 集群伸缩原理
2021/05/15 Redis
python的列表生成式,生成器和generator对象你了解吗
2022/03/16 Python
vue-cli3.0修改打包后的文件名和文件地址,打包后本地运行报错解决
2022/04/06 Vue.js
python图像处理 PIL Image操作实例
2022/04/09 Python