一.前言

那今天这篇文章虽然是介绍javascript中bind、apply和call函数,但是多少也和this有点关联。

假如在前面那场面试末尾,面试官不依不饶继续问你javascript中的this,那看完本篇文章后一定还会有收获。

(本篇文章不会站在this的角度去回答问题,而是重于解释bind、apply和call这三个函数的用法和使用场景)

二.正戏开始

面试官:能解释一下javascript中bind、apply和call这三个函数的用法吗?

我:(这三个函数我也只是了解它们的用法,仅此而已)

我:这三个函数都是用于改变函数运行时内部this的指向的,只是每个函数的用法不一样。

面试官:那你分别说一下具体都怎么用吧。

我:(接着我边回忆之前做过的小练习边回答面试官)

(以下描述和回答均基于浏览环境)

首先是一个很简单的示例

1 var objMM = {

2 name: 'MM',

3 age: 18,

4 getPresonInfo: function(addr){

5 console.log(this.name + "年龄" + this.age + " 地址: " + addr);

6 }

7 };

8

9 var objZZ = {

10 name: 'ZZ',

11 age: 28,

12 getPresonInfo: function(addr){

13 console.log(this.name + "年龄" + this.age + " 地址: " + addr);

14 }

15 }

16

17

18 objMM.getPresonInfo('上海');

19

20 objZZ.getPresonInfo('深圳');

18行和20行的打印信息分别为:

bind方法

首先是bind方法,它的基本语法为 targetFunction.bind(thisArg,arg1,arg2,...)。

第一个参数thisArg会作为目标函数targetFunction运行时的this值传递给目标函数。

后面的参数列表arg1,arg2,... 是传递给目标函数的参数。

bind方法的返回值是一个目标函数的一个拷贝。

这个拷贝出来的函数运行时this指向的就是调用bind传递的thisArg参数。

并且拷贝函数还拥有调用bind时传递的arg1,arg2,...多个参数。

感觉这段描述把我自己都说晕了。

所以如果觉得语言描述不清楚,就写一个简单的用法示例:

var copyF = objMM.getPresonInfo.bind(objZZ,'远方');

copyF();

这个示例是要在前面第一个示例的基础上运行的。

在结合前面那段晦涩难懂的文字描述,可以这样理解这两行代码:

copyF为objMM.getPresonInfo函数的一个拷贝。

copyF运行时内部的this指向objZZ;

copy函数拥有一个参数'远方'

这样调用copy函数的结果就很显而易见了。

apply方法

apply方法的基本语法为 targetFunction.apply(thisArg,[arg1,arg2])。

第一个参数的作用同bind方法。

第二个参数的作用也是和bind方法相同,只是将参数列表变为数组的形式进行传递。

apply方法的返回值和bind方法就完全不同了,它会直接调用并执行目标函数。

那话不多说,在写一个示例

objMM.getPresonInfo.bind(objZZ,['你管我在哪']);

打印结果:

call方法

call方法的基本语法为 targetFunction.call(thisArg,arg1,arg2,...)。

第一个参数的作用同bind方法,也同apply方法。

第二个参数的作用也是和bind、apply相同,只是形式同bind方法是参数列表形式。

call方法的返回值同apply方法,也是直接调用并执行目标函数。

objMM.getPresonInfo.call(objZZ,'我爱在哪在哪');

打印结果:

面试官:那这些函数你平时用过吗,具体有什么使用场景。

我:(这下惨了,平时还真没咋用过,如实回答)平时在写代码的时候,基本没咋用过。

面试官:那好吧

我:(凉凉)......

三.自我反思

回家后深刻进行了自我反思:平时好像还真的没有使用过这个三个函数呀,不过没关系,现在学还来得及。

于是我开始各种搜罗,然后依照个人理解,将其分为两种使用场景。

(怎么分类不重要,后面的示例才重要)

1.使用场景一:借用函数

借用函数大概意思就是借用现有方法去自己的需求。

在文章开始的第一个示例的基础上,稍作一下修改

1 var objMM = {

2 name: 'MM',

3 age: 18,

4 getPresonInfo: function(addr){

5 console.log(this.name + "年龄" + this.age + " 地址: " + addr);

6 }

7 };

8

9 var objZZ = {

10 name: 'ZZ',

11 age: 28

12 }

这个代码中,objZZ已经没有getPersonInfo这个方法了,假如我们想像objMM那样去打印对象自身的信息怎么办呢?

此时这三个函数就能派上用场了。

1 objMM.getPresonInfo.bind(objZZ,'我爱在哪在哪')(); // ZZ年龄28 地址: 我爱在哪在哪

2 objMM.getPresonInfo.apply(objZZ,['我爱在哪在哪']); // ZZ年龄28 地址: 我爱在哪在哪

3 objMM.getPresonInfo.call(objZZ,'我爱在哪在哪'); // ZZ年龄28 地址: 我爱在哪在哪

在就是javascript里面有很多工具对象(我自己这样叫),比如Math。

Math类有两个函数max和min,一般情况下依照这两个函数的语法只能这样使用:

var maxNum = Math.max(23,197,88,35,109,11);

console.log(maxNum); // 197

var minNum = Math.min(23,197,88,35,109,11);

console.log(minNum); //11

假设现在代码里面有一个数组变量要求出最大最小值,我们又不想自己去实现。

那我们就只能借助Math提供的max和min方法,使用apply函数去实现这个功能。

var arr = [23,197,88,35,109,11];

var maxNum = Math.max.apply(Math,arr);

console.log(maxNum); // 197

var minNum = Math.min.apply(Math,arr);

console.log(minNum); //11

除了Math类之外,数组也有很多api,比如最常见的forEach。

这个方法也只能是数组类型的变量才能使用,那非数组类型的变量要使用怎么办呢?

1 var divCollections = document.getElementsByTagName('html');

2

3 Array.prototype.forEach.bind(divCollections,function(item){

4 console.log(item);

5 })();

6 Array.prototype.forEach.apply(divCollections,[function(item){

7 console.log(item);

8 }]);

9 Array.prototype.forEach.call(divCollections,function(item){

10 console.log(item);

11 });

借用函数的最后一个使用场景就是数据类型判断。

我们知道javascript中使用typeof可以判断一个变量的类型,但是仅限于基础的类型。

比如:number、string、boolean、undefined类型。

其他类型的例如:array、object、null使用typeof 判断类型打印均为“object”

所以我们可以借助Object对象提供的一个函数,准确的知道一个数据的类型。

1 Object.prototype.toString.call(1); // "[Object Number]"

2 Object.prototype.toString.call('1'); // "[Object String]"

3 Object.prototype.toString.call(true); // "[Object Boolean]"

4 Object.prototype.toString.call(undefined); // "[Object Undefined]"

5 Object.prototype.toString.call([]); // "[Object Array]"

6 Object.prototype.toString.call({}); // "[Object Object]"

7 Object.prototype.toString.call(null); // "[Object Null]"

2.使用场景二:实现继承

我们都知道,javascript中最简单的继承代码是通过将子类原型指向父类实例实现的。

1 function Father(name,age){

2 this.name = name;

3 this.age = age;

4 this.sayInfo = function(){

5 console.log(this.name + "年龄: "+ this.age);

6 }

7 }

8

9

10 function Son(name,age){

11 this.name = name;

12 this.age = age;

13 }

14

15 //将子类原型指向父类实例

16 Son.prototype = new Father('我是你爸爸',);

17

18 var s = new Son('Son',1)

19 s.sayInfo(); //打印:Son年龄: 1

那我们可以借助这三个函数实现javascript中的继承。

(这里只写call方法的实现)

1 function Father(name,age){

2 this.name = name;

3 this.age = age;

4 this.sayInfo = function(){

5 console.log(this.name + "年龄: "+ this.age);

6 }

7 }

8

9 function Son(name,age){

10 Father.call(this,name,age)

11 }

12

13

14 var s = new Son('Son',1)

15 s.sayInfo(); //打印:Son年龄: 1

可以看到使用call实现继承时,只需要在子类Son中调用父类的构造函数,并且按照call函数的语法传入所需参数即可。

后面直接使用Son的实例就能调用sayInfo函数。

这种方式说来有点意思,因为前面es5语法的继承是子类原型指向父类实例,也就是通过原型链实现的。

而这种方式的原理又是什么呢?

好奇心驱使,我分别打印了前面es5中原型链实现继承后创建的实例s和使用call实现继承后创建的实例s

从结果可以看到,使用call实现继承,实例化后的对象s本身已经拥有了sayInfo方法。

所以说原型链式的继承和call实现的继承还是有本质的区别的。

那到底里,关于bind、apply、call函数的使用场景就整理完了,下次遇到面试官问应该就不虚了。

(使用场景有可能不全,欢迎大家补充)

四.总结

本篇到此就基本结束了,结合前一篇关于this的文章,javascript中的this基本就没啥大问题了。

当然实际的项目千变万化,还是需要谨慎使用this。

介于本篇文章主要还是解释javascript中bind、apply和call函数的用法,因此后续会在补一篇总结《使用原生Javascript实现bind、apply和call函数》。

最近作者新开通了一个微信公众号。

微信公众号会分享一些自己日常的东西,包括个人总结呀,吸猫日常呀,同时也会分享一些博客上的前端技术文章。

欢迎大家扫码关注~

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[面试官:能解释一下javascript中bind、apply和call这三个函数的用法吗]http://www.zyiz.net/tech/detail-105126.html

bind函数怎么用JAVA_面试官:能解释一下javascript中bind、apply和call这三个函数的用法吗...相关推荐

  1. 华为二面!!!面试官直接问我Java中到底什么是NIO?这不是直接送分题???

    华为二面!!!面试官直接问我Java中到底什么是NIO?这不是直接送分题??? 什么是NIO 缓冲区(Buffer) 缓冲区类型 获取缓冲区 核心属性 核心方法 非直接缓冲区和直接缓冲区 非直接缓冲区 ...

  2. 今天来谈谈面试官最喜欢问JS中的闭包问题吧

    今天来谈谈面试官最喜欢问JS中的闭包问题吧 1.什么是闭包? 闭包是指有权访问另外一个函数作用域中的变量的函数,闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在.闭包就是函数的&qu ...

  3. 面试官让我讲讲Java中的锁,我笑了

    转载自  面试官让我讲讲Java中的锁,我笑了 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁 ...

  4. 一位面试官询问我:Java中的JVM内存溢出和内存泄露是什么?我这么回答成功拿到了offer

    一位面试官询问我:Java中的JVM内存溢出和内存泄露是什么?我这么回答成功拿到了offer. 墨眉无锋墨家代码 2020-11-22 20:16:50 10525 收藏 56 分类专栏: Java ...

  5. 如何在JavaScript中使用apply(?),call(?)和bind(➰)方法

    by Ashay Mandwarya ?️?? 由Ashay Mandwarya提供吗? 如何在JavaScript中使用apply(?),call(?)和bind(➰)方法 (How to use ...

  6. atoi函数_吊打面试官 | 腾讯经典考点写代码实现atoi函数

    点击蓝字关注我哦 以下是本期干货视频视频后还附有文字版本哦 ▼<腾讯经典考点-写代码实现atoi函数>▼ ps:请在WiFi环境下打开,如果有钱任性请随意 在腾讯面试时,经常会被问到如何用 ...

  7. 面试官:手写一个call、apply、bind?

    前言 相信不少面试中涉及this的问题不少.而在JavaScript中this的绑定有四种类型,优先级分别为 new绑定>显式绑定>隐式绑定>默认绑定,这里我们也浅浅提及一下这四种的 ...

  8. .实现 linkedlist 类java_面试官:兄弟,说说 ArrayList 和 LinkedList 有什么区别

    来自公众号:沉默王二 ArrayList 和 LinkedList 有什么区别,是面试官非常喜欢问的一个问题.可能大部分小伙伴和我一样,能回答出"ArrayList 是基于数组实现的,Lin ...

  9. 此上下文中不允许函数定义。_面试官:那我们来说说执行上下文吧

    当 JS 引擎处理一段脚本内容的时候,它是以怎样的顺序解析和执行的?脚本中的那些变量是何时被定义的?它们之间错综复杂的访问关系又是怎样创建和链接的?要解释这些问题,就必须了解 JS 执行上下文的概念. ...

  10. 面试官:你知道Java中的回调机制吗?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:22j.co/cFPf          正文    调用和 ...

最新文章

  1. python主要数据变量及其类型说明_Python的数据类型和变量
  2. 计算机主机清理步骤,怎么清理主机灰尘 清理灰尘教程
  3. C++中的野指针问题
  4. 2015蓝桥杯省赛---java---C---6(奇妙的数字)
  5. HeadFirst设计模式篇四:工厂模式
  6. Atitit. null错误的设计 使用Optional来处理null
  7. jQuery2.x源码解析(设计篇)
  8. c语言单链表怎么循环链表,链表之循环单链表(用C语言描述)
  9. CISCO 5510 ASDM的实战总结
  10. 联想重装系统去掉保护_经验:联想硬盘保护系统EDU 7.0清除日志
  11. 小米8的usb计算机连接不上,小米手机usb已连接电脑不显示怎么办
  12. CDN是什么?使用CDN有什么优势?
  13. php yar2,[原]PHP-yar拓展源码解读二-protocol篇
  14. 计算机维护工具全能版,USBOS V3.0彪悍版
  15. 2018年sfdc工作总结_常见Salesforce 异常
  16. 基于单片机的6位电子时钟
  17. 滴滴打车创新盈利方式
  18. Ubuntu Conda创建环境
  19. 阿里云基本概念与基础架构(一)
  20. 计算机JW,被它颜值所吸引:Casio卡西欧JW-200SC计算器 入手体验

热门文章

  1. 真题很重要,用科学的态度批判性地对待真题同等重要!
  2. 50个GMAIL申请,来吧来吧!
  3. 10-ret/retf+call+mul
  4. 数据--第25课 - 队列课后练习
  5. 联机交易场景持续拓展,巨杉数据库中标吉林省农信
  6. 凸优化第五章对偶 5.9 广义不等式
  7. SecureCRT 颜色
  8. [ HNOI 2015 ] 亚瑟王
  9. 爬虫入门系列(四):HTML 文本解析库 BeautifulSoup
  10. .NET常用类库--苏飞合集