apply和call都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部this的指向);
 
如果使用apply或call方法,那么this指向他们的第一个参数,apply的第二个参数是一个参数数组,call的第二个及其以后的参数都是数组里面的元素,就是说要全部列举出来;
 
他们的常用用法
1.数组之间的追加;
2.获取数组中的最大值和最小值,利用他们扩充作用域拥有Math的min和max方法;
由于没有什么对象调用这个方法,所以第一个参数可以写作null或者本身;
var  numbers = [5, 458 , 120 , -215 ]; 
var  maxInNumbers = Math.max.apply(Math, numbers),   //458

       maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458
3.验证是否是数组(前提是toString()方法没有被重写过)
function   isArray(obj){ 
    return Object.prototype.toString.call(obj) === '[object Array]' ;

}
4.让类数组拥有数组的方法
 
比如arguments对象,获取到的文档节点等,并没有数组的那些方法:
Array.prototype.slice.apply(argument); //理论上来说这个比较快,直接在原型上查找slice方法
                                                                 //但实际上比较慢
或者
[].slice.apply(arguments); //理论上来说这个比较慢,因为要Array做一个实例化再查找slice方法
                                        //实际上比较快,因为现在的各种自动化工具会把上一种方法转换为这种,而第二种代码比较简洁,所以会比较快;
 
 
bind()--也是改变函数体内this的指向;
bind会创建一个新函数,称为绑定函数,当调用这个函数的时候,绑定函数会以创建它时传入bind()方法的第一个参数作为this,传入bind()方法的第二个及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数;
 
bind与apply、call最大的区别就是:bind不会立即调用,其他两个会立即调用
例子:
 
如果多次调用bind,那么多出来的次数都是无效的,
 
 
三个的使用区别:
都是用来改变函数的this对象的指向的;
第一个参数都是this要指向的对象;
都可以利用后续参数传参;
bind是返回对应函数,便于稍后调用,apply、call是立即调用;
 
 
 

详解call(),apply()和bind()

http://blog.csdn.net/u014267183/article/details/52610600

原创 2016年09月21日 17:32:57
  • 4753

之前看了点es6的箭头函数,为了搞懂箭头函数的this,看了很多文章,也顺便看了几个绑定函数,发现很多以前没注意的问题,收获不少。

之前就在网上的笔试题中看过用js实现bind()函数,没怎么在意,以为既然都是用来进行上下文绑定的,用call或者apply应该就能实现。现在看,我还是图样图森破。

先来讲一下call()和apply()吧,对于这两个函数,我是看自己的书学习的,学的时候没觉的有什么问题,但是我查了一下网上的关于call()和apply()的文章,尼玛啊,这说都是些什么啊!!看着真费劲。

其实,call()和apply()就是改变函数的执行上下文,也就是this值。他们两个是Function对象的方法,每个函数都能调用。他们的第一个参数就是你要指定的执行上下文,第二个用来传递参数(说第二个不准确,应该说第二部分,因为参数可以传多个),也就是传给调用call和apply方法的函数的参数。说白了,就是调用函数,但是让它在你指定的上下文下执行,这样,函数可以访问的作用域就会改变。下面看点代码:

function apply1(num1, num2){
    return sum.apply(this, [num1, num2]);
    }
function call1(num1, num2){
    return sum.call(this, num1, num2);

}

这里,我们执行环境传的是this,也就是说没改变函数的执行上下文。这两段代码,只是想告诉你call和apply的区别。

call的第二部分参数要一个一个传,apply要把这些参数放到数组中。这就是他们的区别,真的就这么点区别!!!

然后,不得不说的一点:它们的第二个参数都可以传arguments。

—————————————————————————————————————————————————————————————————————————————

下面来讲bind()函数,bind()是es5中的方法,他也是用来实现上下文绑定,看它的函数名就知道。bind()和call与apply不同。bind是新创建一个函数,然后把它的上下文绑定到bind()括号中的参数上,然后将它返回。

所以,bind后函数不会执行,而只是返回一个改变了上下文的函数副本,而call和apply是直接执行函数。

下面代码可以反映出这点,而且也显示了bind的用法(后面的代码皆取自张鑫旭大神的博客)

var button = document.getElementById("button"),
text = document.getElementById("text");
button.onclick = function() {
alert(this.id); // 弹出text
}.bind(text);

但由于ie6~ie8不支持该方法,所以若想在这几个浏览器中使用,我们就要模拟该方法,这也是面试常考的问题,模拟的代码如下:

if (!function() {}.bind) {
Function.prototype.bind = function(context) {
var self = this
, args = Array.prototype.slice.call(arguments); return function() {
return self.apply(context, args.slice(1));
}
};
}

就是这段代码,纠正了我长久以来的一个误区。下面来讲一下这段代码

首先,我们判断是否存在bind方法,然后,若不存在,向Function对象的原型中添加自定义的bind方法。

这里面var self = this这段代码让我很困扰,按理说,prototype是一个对象,对象的this应该指向对象本身,也就是prototype,但真的是这样吗。看看下面的代码:

function a(){};

a.prototype.testThis = function(){console.log(a.prototype == this);};

var b = new a();

b.testThis();//false

显然,this不指向prototype,而经过测试,它也不指向a,而指向b。所以原型中的this值就明朗了。指向调用它的对象。

Array.prototype.slice.call(arguments);

接下来就是上面这段代码,它会将一个类数组形式的变量转化为真正的数组。为啥呢,其实书上并没有说slice还有这样的用法,也不知道是谁发明的。slice的用法可以顺便上网查一下,就能查到。但要更正一点,网上的介绍说slice有两个参数,第一个参数不能省略。然而我不知道是我理解的问题还是咋地,上面这段代码tmd不就是典型的没传参数吗!!!arguments是传给call的那个上下文,前面讲过,不要弄混(由于arguments自己没有slice方法,这里属于借用Array原型的slice方法)。而且经过测试,若果你不给slice传参数,那就等于传了个0给它,结果就是返回一个和原来数组一模一样的副本。

这之后的代码就很好理解,返回一个函数,该函数把传给bind的第一个参数当做执行上下文,由于args已经是一个数组,排除第一项,将之后的部分作为第二部分参数传给apply,前面讲过apply的用法。

如此,我们自己的这个bind函数的行为就同es5中的bind一样了。

apply、call、bind区别、用法的更多相关文章

  1. call,apply,bind的用法与区别

    1.call/apply/bind方法的来源 首先,在使用call,apply,bind方法时,我们有必要知道这三个方法究竟是来自哪里?为什么可以使用的到这三个方法? call,apply,bind这 ...

  2. JS之apply,call,bind区别

    为了加深对基础知识的理解,今天再复习下js中的apply,call,bind的区别和用法.整理笔记的过程也是一个再次学习的过程. apply和call js中的调用apply和call方法可以改变某个 ...

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

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

  4. call和apply和bind区别

    call和apply特征一样 都是用来调用函数 立即调用 但是可以在调用函数的同时 通过第一个参数指定函数内部this的指向 call 调用的时候 参数必须以参数列表的形式进行传递 也就是以逗号分隔的 ...

  5. call、apply、bind的用法

    数组追加 //用apply拼接 var arr1=[12,'name:foo',2048]; var arr2=['Joe','Hello']; Array.prototype.push.apply( ...

  6. javascript中call()、apply()、bind()的用法理解

    一.bind的用法 第一个:obj.showInfo('arg','arg_18');中传的2个参数通过showInfo方法改变的是obj下中的name和age 第二个:obj.showInfo.bi ...

  7. JS中的call()、apply() 以及 bind()方法用法总结

    JS中的call()方法和apply()方法用法总结  : 讲解: 调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域. function add(c,d){ return thi ...

  8. javascript中call()、apply()、bind()的用法终于理解

    其实是一个很简单的东西,认真看十分钟就从一脸懵B 到完全 理解! 先看明白下面: 例1 obj.objAge;  //17 obj.myFun()  //小张年龄undefined 例2 shows( ...

  9. (转)javascript中call()、apply()、bind()的用法

    其实是一个很简单的东西,认真看十分钟就从一脸懵B 到完全 理解! 先看明白下面: 例1 obj.objAge;  //17 obj.myFun()  //小张年龄undefined 例2 shows( ...

  10. <JavaScript> call()、apply()、bind() 的用法

    其实是一个很简单的东西,认真看十分钟就从一脸懵B 到完全 理解! 先看明白下面: 例 1 obj.objAge; obj.myFun() // 小张年龄 undefined   例 2 shows() ...

随机推荐

  1. 数据库(学习整理)----7--Oracle导入导出数据库文件

    Oracle导入本地数据库操作手册 1.旧数据库忘记了密码,首先进入cmd:1)输入:sqlplus/nolog2)输入:connect/as sysdba3)输入:alter user sys id ...

  2. Alpha冲刺(二)

    Information: 队名:彳艮彳亍团队 组长博客:戳我进入 作业博客:班级博客本次作业的链接 Details: 组员1(组长)柯奇豪 过去两天完成了哪些任务 学习并配置了ssm框架(用于前后端交 ...

  3. 【转】android 手势识别和VelocityTracker

    参考地址: http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1020/448.html http://www.jcodecraeer.co ...

  4. HackTen 格式化TextView的文本

    1.概要:     TextView是Android提供的一个简单却功能强大的UI控件.读者可以在应用程序中通过多种方法使用不同样式的文本. 监管TextView并不支持所有HTML标签,但是用于格式 ...

  5. Expression表单式树

    余于项目中逢Expression(表达式树),然今未明其用途也,记之以温. using System; using System.Collections.Generic; using System.L ...

  6. WebStrom背景色设置

    Ctrl Alt S快速打开setting:

  7. Navicat premium连不上Oracle的问题解决

    1.ORA-28547: 这是因为oci.dll版本不对.Navicat本地的OCI版本与Oracle服务器服务器不符造成的. 或者 打开Navicat premium客户端:Tool->Opt ...

  8. 【bzoj2140】: 稳定婚姻 图论-tarjan

    [bzoj2140]: 稳定婚姻 哎..都是模板题.. 一眼看过去 哇 二分图哎 然后发现好像并不能匈牙利算法 自己xjb画两张图,发现二分图左向右连配偶的边,然后右向左连交往过的边 然后如果Bi G ...

  9. 【转】C# String 与 Char[] 数组 相互转换

    源地址:http://blog.csdn.net/razilfelix/article/details/52289663 string 转换成 Char[] string ss = "abc ...

  10. 一个很棒的PHP缓存类,收藏下

    <?php class Cache { /** 缓存目录 **/ var $CacheDir = './cache'; /** 缓存的文件 **/ var $CacheFile = ''; /* ...