bind、apply、call解析

来源:互联网 发布:ubuntu grub 命令 编辑:程序博客网 时间:2024/05/20 15:39
目录
  1. 学习来源
  2. 过去的困惑
  3. 格式
  4. 相同之处
  5. 不同
  6. 小小知识点

1. 学习来源

推荐一篇教程,用例丰富、描述准确、总结到位:
深入浅出妙用 Javascript 中 apply、call、bind

上文作者的总结

  • apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
  • apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
  • apply 、 call 、bind 三者都可以利用后续参数传参;
  • bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

2. 过去的困惑

过去对于js的学习就停留于“传参直接调用方法”,认为Array.prototype.push.apply这样的语句有点抽象,无法理解。

// 用例目的:把 array2 追加到 array1 的尾部var array1 = [1,2,3,4,5]; var array2 = [7,7,7,7,7]; Array.prototype.push.apply(array1, array2);            /* array1 值为  [1,2,3,4,5,7,7,7,7,7] */// 实际就是以array1这一数组变量调用了Array对象的push方法// 并且将array2中的每一个元素拆解为一个push方法的参数

具体扩展后:

Array.prototype.push.apply(array1,  array2);等同于如下写法:array1.push(array2[0],  array2[1],  array2[2],  array2[3],  array2[4]);

es6优化后:

// 使用es6的"...扩展运算符"取代apply方法array1.push(...array2) ;

追加一个小栗子:

// ES5 的写法Math.max.apply(null, [14, 3, 77])// ES6 的写法Math.max(...[14, 3, 77])// 等同于Math.max(14, 3, 77);

3. 格式

var func = function (arg1, arg2) {};func.apply(this, [arg1, arg2]);       // 调用func函数,并且指定this为当前作用域,并且把两个参数以数组的形式传入func.call(this, arg1, arg2);            // 调用func函数,并且指定this为当前作用域,顺序传入参数 func.bind(this);                            // 为func函数绑定作用域为“当前的this”,留作后续调用

4. 相同之处

bing、apply、call三者都:

  • 用于改变函数指向的this对象,即函数作用域;
  • 传入的第一个参数即为this指向的新对象,即“想要指定的上下文”
  • 都可以传入参数(bind的传参类似于传入默认值)

5. 不同

bind: 创建并返回一个新函数,并绑定每一次的this,但并不调用
apply:指定此次的this,并且立即调用;(以数组形式传参)
call:指定此次的this,并且立即调用;(多参数逐个传参)

6. 小小知识点

6.1 多次调用bind是无效的

var bar = function(){    console.log(this.x);}var foo = {    x:3}var sed = {    x:4}var func = bar.bind(foo).bind(sed);func();          // 输出3,绑定的上下文是foo var fiv = {    x:5}var func = bar.bind(foo).bind(sed).bind(fiv);func();         // 输出3,绑定的上下文依然是foo

文首作者解释的无效原因

bind() 的实现,相当于使用函数在内部包了一个 call / apply ,第二次 bind() 相当于再包住第一次 bind() ,故第二次以后的 bind 是无法生效的。

对于这段话,我的理解是:
对于bind调用链来说,执行顺序是从后往前的。
var func = bar.bind(foo).bind(sed).bind(fiv);
这一句的实际调用顺序是bind(fiv) ==> bind(sed) ==> bind(foo);
也可以看做 ( ( (bar.bind(fiv)) ).bind(sed) ).bind(foo);



作者:daisimin7
链接:http://www.jianshu.com/p/797218ea32e2
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原创粉丝点击