为什么80%的码农都做不了架构师?>>>   

call(),apply(),bind() 函数大家可能都有所了解,但是在平时搬砖过程中很可能或者基本没用过,学过但都淡忘了。

但是在大量第三方的框架(库),甚至js自己都在 源码中大量使用 call,apply 函数。所以今天和大家仔细讨论下它们在 开发中的应用场景 。

1 . 它们是啥意思

1.1 作用

  1. 他们的作用都是改变函数内部的this
  2. 这三个函数都是函数对象的方法,也就是说只有函数才可以直接调用这些方法。

ps:call,apply,bing属于this显示绑定,还有好几种其他的this绑定方式,感兴趣的可以点这里。

1.2 三者区别

  • 参数: 三个函数的第一个参数都是需要绑定的 this

call: 可以有n个参数,从第二个参数开始的所有参数都是原函数的参数。

`apply`:只有两个参数,并且第二个参数必须为数组,数组中的所有元素一一对应原函数的参数。`bind`: 只有一个参数,即要绑定的this。
    call 语法:  foo.call(this, arg1,arg2, ... ,argn );apply 语法: foo.apply(this, [ arg1,arg2, ... ,argn ] );bind 语法:  foo.bind(this);
  • 调用:

call,apply: 调用后立即执行原函数。

`bind`: 调用后返回已经绑定好this的函数。

小例子一枚:

function foo(a,b){console.log(a+b);}foo.call(null,'海洋','饼干');        // 海洋饼干  这里this指向不重要就写null了foo.apply(null, ['海洋','饼干'] );   // 海洋饼干var fun = foo.bind(null);fun('海洋','饼干');                  // 海洋饼干

2 .它们能干啥事

这是我们今天讨论的主题,这三个函数如何应用?什么情况下使用?能改变this指向又能咋滴?

2 .1 处理伪数组 (最常用)

先考虑一个问题,如果你使用var arr = document.getElementsByTagName('li')获取了5个li元素,你现在需要获取其中的第2,3,4三个元素,你会怎么做?

这样arr.slice(1,4);? 啊哦,TypeError -- arr.slice is not a function(slice不是函数),数组操作在日常搬砖中非常常见,我见过最傻的解决这个问题的方式是使用循环,将需要的元素一个个添加到一个新数组里0.0,下面我介绍的方法完全可以在实战中使用,可以给你的代码加分哦,非常方便简洁(中高级前端程序员中,算是基本操作了)。

先要介绍一个概念( 伪数组 ),这也是为什么我们刚刚slice切割数组时出错的原因: (对新手来说算是干货了,知道的可以跳过)

什么是伪数组?( 字面的意思已经呼之欲出了 )

  1. 有length属性
  2. 能按索引存储数据
  3. 能像遍历数组一样来遍历
  4. 不能使用数组的push()、slice()等方法

简单来说就是可以像数组一样操作的对象,但是没有数组的方法。

js中存在大量伪数组,如 :

1. function的arguments对象。
2. getElementsByName(),getElementsByTagName(),childNodes/children 等方法的返回值。
3. 还有比较常见的jquery,使用它获取的元素也是伪数组。

回到原来的问题,如何截取伪数组中的元素:伪数组没有这些方法,我们'借用'Array的slice不就行了

[].slice.call(arr,1,4);  // 推荐写法

不想借用你可以直接给伪数组添加一个slice函数,如

arr.slice = [].slice;
arr.slice(1,4);

当然,'借用' 更方便,直接添加会导致伪数组对象'污染'。

如果可以随意改变原对象,可以 直接将其转成真正的数组对象

[].slice.call(arr);

2 .2 继承

继承方式多种多样,我们现在讨论的这种是其中很重要的一种实现方式,用call实现 js 构造函数继承 。

  • 单继承
function person(name){this.name = name
}
function man(name){this.age = '男';person.call(this,name);              // 继承 man
}
var me = new man('海洋饼干');console.log(me.name,me.age);             // '海洋饼干' '男'
  • 多继承
function person(name){this.name = name
}
function man(name){this.age = '男';
}
function manProgrammer(name){this.girlfriend = null;person.call(this,name);  // 继承 personman.call(this,name);     // 继承 man
}
var me = new manProgrammer('海洋饼干');console.log(me.name,me.age,me.girlfriend);   // '海洋饼干' '男' null

2 .3 this 硬绑定 --- bind

将一个对象强制且永久性绑定到函数的this上,使用call,apply或者其他的绑定方式都无法改变(除了new绑定,当然,可以手动撸一个new都无法改变的硬绑定)

直接看例子:

var fun ;
var obj = {a : 1,foo : function(){var _this = this;            //平时有没有过这种写法? 为了防止this指向问题//将this赋值给一个变量,间接维持了this的安全性fun = function(){console.log(_this.a);}}
}
obj.foo();
fun();                 // 1var obj1 = { a : 2}
obj.foo.call(obj1);    // 直接修改_this所绑定的值,boom了
fun();                 // 2

但是这种方法感觉上是在逃避问题,直接不使用this了 ? 这真的不是什么好的解决问题的态度。下面使用我们的bind来优化一下:

var fun ;
var obj = {a : 1,foo : function(){            // 不使用 _this, 避免无谓的变量声明fun = function(){console.log(this.a);}.bind(this);            // 代码很简洁,很漂亮(b格)}
}
var obj1 = { a : 2}
obj.foo();
fun();             // 1
fun.call(obj1);    // 1  call ,apply等绑定 无法修改// 这里和上面call的位置不同是因为this所处于不同的位置

这样替代 _this 很规(zhuang)范(b)

ps:call,apply,bing属于this显示绑定,还有好几种其他的this绑定方式,感兴趣的可以点这里。

2 .4 取数组最大最小值

Math.max和min方法,接收多个参数,比较出极值,这里用到apply的一个默认功能:展开数组传入一个数组参数就可以默认将这个数组转成一个个参数的形式赋给原函数

var num = [6,9,-3,-5];
console.log(Math.max.apply(Math,num)); // 9  等价  console.log(Math.max(6,9,-3,-5));
console.log(Math.min.apply(Math,num)); // -5 等价  console.log(Math.min(6,9,-3,-5));

2 .5 合并数组

合并数组常见有三种方式,1.循环 2.Array的concat() 3. 使用apply()合并

这里是使用最简便的apply

var a = [1,2,3];
var b = [4,5,6];
[].push.apply(a,b);    // 借用数组的push方法 等价 a.push(4,5,6);
console.log(a);        // [1, 2, 3, 4, 5, 6]

最后

这里推荐一下我的前端学习交流裙:731771211,里面都是学习前端的,群里会不定期更新最新的教程和学习方法,有想学习web前端的,或是转行,或是大学生,还有工作中想提升自己能力的web前端党欢迎加入。

转载于:https://my.oschina.net/zybc/blog/2221734

JavaScript—call, apply, bind 函数(20)相关推荐

  1. 手写call,apply,bind函数

    涉及面试题 call,apply,bind函数内部实现是怎样的? 考虑两点: 第一个参数为undefined或null的时候,那么会转变为window 改变了this执行,让新的对象可以执行该函数. ...

  2. call、apply、bind函数详解

     我们都知道call,apply,bind函数都是为了改变this的指向,那么对于三种函数有什么相同点有什么不太点或者有什么应用呢?下面我们来进行介绍 call与apply函数  在javascrip ...

  3. JavaScript简餐——那些函数属性与方法(call、apply和bind)

    文章目录 前言 一.arguments对象的callee属性 二.函数的caller属性 三.new.target 四.call.apply和bind方法 1.call方法 2.apply方法 3.b ...

  4. javascript中实例对象和构造函数关系、原型语法、原型链、call实现继承、apply调用函数、bind拷贝函数、拷贝继承、class类、super、严格模式、高阶函数、闭包、递归、es6简介

    实例对象和构造函数的关系及原型: 实例对象是通过构造函数创建出来的,实例对象的构造器constructor就是指向构造函数的:每个实例对象中的同一方法的指向是各不相同的,但是其属性值相同的属性可以相同 ...

  5. JavaScript中的call,apply,bind学习总结

    JavaScript 中的 call, apply, bind 这三个函数的作用和区别在各大论坛都被讨论了很多次了,但是我一直都还没来得及好好总结,这次正好看到了一个很不错的关于JavaScript ...

  6. JavaScript中的call,apply,bind区别及应用(包含手写call/apply/bind)

    目录 一.使用目的 二.三者分别是如何定义的及区别(摘自MDN) 三.在程序中收获 四.三者的具体应用 四.手写bind,apply,call 今天在读程序题的时候,遇到call,apply,bind ...

  7. Javascript 中 apply、call、bind

    在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向. JavaScript 的一大 ...

  8. [转] 深入浅出 妙用Javascript中apply、call、bind

    [From] http://www.admin10000.com/document/6711.html 网上文章虽多,大多复制粘贴,且晦涩难懂,我希望能够通过这篇文章,能够清晰的提升对apply.ca ...

  9. 深入Javascript中apply、call、bind

    最近在看一下node package的源码,发现很多里面都包含了function这个对象的apply.call.bind这三个方法,于是想拿出来再看看.. apply.call 在 javascrip ...

  10. 【优雅代码】深入浅出 妙用Javascript中apply、call、bind

    这篇文章实在是很难下笔,因为网上相关文章不胜枚举. 巧合的是前些天看到阮老师的一篇文章的一句话: "对我来说,博客首先是一种知识管理工具,其次才是传播工具.我的技术文章,主要用来整理我还不懂 ...

最新文章

  1. 嵌入式技术在智能电网的应用
  2. Tableau必知必会之用 Page 功能创建你的动态视图
  3. java 8 stream_Java 8 Stream示例
  4. shell 提取sql 的字段名表名_SQL代码风格规范
  5. mysql item_MySQL源代码:关于MySQL的Item对象
  6. jquery ztree 设置勾选_047 JAVA-jQuery
  7. ROS在类中发布和接受消息(自定义消息)
  8. PHP-php://(类型)访问各个输入/输出流以及全局变量$HTTP_RAW_POST_DATA讲解
  9. python3.8.5-Python 3.8.5 正式发布
  10. Jensen不等式及其应用
  11. 红linux系统,红帽子linux系统
  12. 最新字节跳动面试题之堆排序
  13. 程序猿 网站 | 常用 技术学习网站
  14. tp6的运行流程+一个完整的tp6请求的流程:
  15. 使用Tensorflow Lite在Android上进行AI危害检测
  16. 如何将谷歌浏览器指定网页的背景颜色调成黑色,其他网页背景颜色不变——以HDLBits为例
  17. 任务栏可以点,电脑桌面却不显示内容的解决方法
  18. Marlin固件 ---- G_Code 命令解析
  19. Openlayers设置请求瓦片大小
  20. 好用的图片翻译器有哪些?这3个工具你们不能不知道

热门文章

  1. 牛客网——复杂字符串排序
  2. python read文件的r和rb的区别
  3. JS页面打开方式丶对话框及页面跳转方式
  4. 在python 中is和= = 的区别
  5. 2008是中国的奥运年
  6. 程序员职业规划(一篇来自阿里Java工程师对工作3年左右程序员的职业建议和应该掌握的职业技能)...
  7. CSS3 鲜为人知的属性-webkit-tap-highlight-color的理解
  8. android---gettag()与settag()的妙用
  9. eclipse bookmark的使用
  10. 查看电脑端口占用情况