关于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的用法的更多相关文章

  1. JavaScript学习(2)call&apply&bind&eval用法

    javascript学习(2)call&apply&bind&eval用法 在javascript中存在这样几种特别有用的函数,能方便我们实现各种奇技淫巧.其中,call.bi ...

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

    这篇文章主要给大家对比分析了javascript中call,apply,bind三个函数的用法,非常的详细,这里推荐给小伙伴们.   关于call,apply,bind这三个函数的用法,是学习java ...

  3. js call().apply().bind()的用法

    function Person(age) { this.age = age; } Person.prototype.sayHi = function (x, y) { console.log((x + ...

  4. call,apply,bind的用法及区别

    <script> function test(){ console.log(this) } // new test(); //函数调用call方法的时候,就会执行. //call的参数:第 ...

  5. ES5-call,apply,bind的用法

    区别bind()与call()和apply()? 1. Function.prototype.bind(obj) : * 作用: 将函数内的this绑定为obj, 并将函数返回2. 面试题: 区别bi ...

  6. 理解 JavaScript call()/apply()/bind()

    理解 JavaScript this 文章中已经比较全面的分析了 this 在 JavaScript 中的指向问题,用一句话来总结就是:this 的指向一定是在执行时决定的,指向被调用函数的对象.当然 ...

  7. 如何实现new,call,apply,bind的底层原理。

    new做了什么? new是用来实例化对象的,当new了一个对象后 1.创建一个新对象 2.将构造函数的作用域赋值给新对象(this指向新对象) 3.执行构造函数里面的代码(为这个新对象添加属性) 4. ...

  8. js中call、apply、bind的用法

    原文链接:http://www.cnblogs.com/xljzlw/p/3775162.html var zlw = { name: "zlw", sayHello: funct ...

  9. js中bind的用法,及与call和apply的区别

    call和apply的使用和区别不再做阐述,可以参考我的另一篇随笔<JavaScript中call和apply方法的使用>(https://www.cnblogs.com/lcr-smg/ ...

随机推荐

  1. Travis CI用来持续集成你的项目

    这里持续集成基于GitHub搭建的博客为项目 工具: zqz@ubuntu:~$ node --version v4.2.6 zqz@ubuntu:~$ git --version git versi ...

  2. 《Django By Example》第五章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者@ucag注:大家好,我是新来的翻译, ...

  3. 9、 Struts2验证(声明式验证、自定义验证器)

    1. 什么是Struts2 验证器 一个健壮的 web 应用程序必须确保用户输入是合法.有效的. Struts2 的输入验证 基于 XWork Validation Framework 的声明式验证: ...

  4. 微信网页开发之获取用户unionID的两种方法--基于微信的多点登录用户识别

    假设网站A有以下功能需求:1,pc端微信扫码登录:2,微信浏览器中的静默登录功能需求,这两种需求就需要用到用户的unionID,这样才能在多个登录点(终端)识别用户.那么这两种需求下用户的unionI ...

  5. Android Studio分类整理res/Layout中的布局文件(创建子目录)

    res/layout中的布局文件太杂,没有层次感,受不了的我治好想办法解决这个问题. 前几天看博客说可以使用插件分组,可惜我没找到.知道看到另一篇博客时,才知道这个方法不能用了. 不能用插件,那就手动 ...

  6. Atitit  godaddy 文件权限 root权限设置

    Atitit  godaddy 文件权限 root权限设置 1. ubuntu需要先登录,再su切换到root1 2. sudo 授权许可使用的su,也是受限制的su1 3. ubuntu默认吗roo ...

  7. 一切从“简”,解放IT运维人员

    运维人的神技 运维既是个技术活儿也是个苦差事,而运维人员被期望有着无限的技能:主机.存储.网络.操作系统样样精通,而且还要会写SQL.shell.开发语言java..net.python等等,对业务更 ...

  8. TCP/IP之Nagle算法与40ms延迟

    Nagle算法是针对网络上存在的微小分组可能会在广域网上造成拥塞而设计的.该算法要求一个TCP连接上最多只能有一个未被确认的未完成的小分组,在该分组确认到达之前不能发送其他的小分组.同时,TCP收集这 ...

  9. 警惕!高版本VS发布时预编译导致Mono中Razor找不到视图

    早前一段时间,一位朋友在Q群里面找到我,说它按照<Linux.NET学习手记>的操作,把一个ASP.NET MVC 4.0的项目部署到Mono之后出现Razor无法找到视图的现象.当时费了 ...

  10. .NET Core dotnet 命令大全

    dotnet 命令大全,让你理解dotnet 命令. 本文将以一个实例串起 dotnet 所有命令,让你玩转dotnet 命令. 本篇文章编写环境为windows 10 ,dotnet 命令同样适用于 ...