js中apply和call的理解与使用方法


Posted in Javascript onNovember 27, 2019

前言

关于call和apply,以前也思考良久,很多时候都以为记住了,但是,我太难了。今天我特地写下笔记,希望可以完全掌握这个东西,也希望可以帮助到任何想对学习这个东西的同学。

一.apply函数定义与理解,先从apply函数出发

在MDN上,apply的定义是:

“apply()方法调用一个具有给定this值的函数,以及作为一个数组(或类似数组对象)提供的参数。”

我的理解是:apply的前面有个含有this的对象,设为A,apply()的参数里,也含有一个含有this的对象设为B。则A.apply(B),表示A代码执行调用了B,B代码照常执行,执行后的结果作为apply的参数,然后apply把这个结果所指代表示的this替换掉A本身的this,接着执行A代码。

比如:

var aa = {
  _name:111,
  _age:222,
  _f:function(){
   console.log(this)
   console.log(this._name)
  }
 }
 var cc = {
  _name:0,
  _age:0,
  _f:function(){
   console.log(this)
   console.log(this._name)
  }
 }
 cc._f.apply(aa)//此时aa表示的this就是aa本身
 cc._f.apply(aa._f)//此时aa._f表示的this就是aa._f本身
 
 /**
  * 此时aa._f()表示的this,就是执行后的结果本身。aa._f()执行后,没有返回值,所以应该是undefined,而undefined作为call和apply的参数时,call和apply前面的方法 cc._f 的this会替换成全局对象window。
  * 参考MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply 的参数说明
  */
 cc._f.apply(aa._f())

执行结果:

1.参数为aa

js中apply和call的理解与使用方法

这两行的打印的都是来自 cc._f 方法内的那两句console 。aa的时候算是初始化,里面的 aa._f 方法没有执行。

2.参数为aa.f

js中apply和call的理解与使用方法

这两行的打印的都是来自 cc._f 方法内的那两句console 。aa.f 的时候应该也算是初始化,或者是整个函数当参数传但是不执行这个参数,即 aa._f 方法没有执行。

3.参数为aa.f()

js中apply和call的理解与使用方法 

这四行的打印,前面两行来自 aa._f() 方法执行打印的;后面两行是来自cc._f()方法打印的。

后两行解析:aa._f()执行后,没有返回值,所以是undefined,在apply执行解析后,cc._f()的this变成的window,所以打印了window。window里面没有_name这个属性,所以undefined。

 二.apply与call的区分

1.apply()

A.apply(B, [1,2,3]) 后面的参数是arguments对象或类似数组的对象,它会被自动解析为A的参数;

对于A.apply(B) / A.call(B) , 简单讲,B先执行,执行后根据结果去执行A。这个时候,用A去执行B的内容代码,然后再执行自己的代码。

比如:

var f1 = function(a,b){
  console.log(a+b)
 }
 var f2 = function(a,b,c){
  console.log(a,b,c)
 }
 f2.apply(f1,[1,2])//1 2 undefined

先执行f1,f1执行后(f1是f1,不是f1()执行方法,所以console.log(a+b)这行代码并没有执行,相当于,初始化了代码f1),由于没有返回值,所以结果是undefined,f2执行的时候this指向window;参数中的 ” [1,2] “,解析后变成 f2 的参数 “ 1,2,undefined ”,执行f2方法后,打印出1,2,undefined三个值

2.call()

A.call(B, 1,2,3) 后面的参数都是独立的参数对象,它们会被自动解析为A的参数;

比如: 

var f1 = function(a,b){
  console.log(a+b)
 }
 var f2 = function(a,b,c){
  console.log(a,b,c)
 }
 f2.call(f1,[1,2])//[1,2] undefined undefined
 f2.call(f1,1,2)//1 2 undefined

参数中的 ” [1,2] “,因为传入了一个数组,相当于只传入了第一个参数,b和c参数没有传。解析后变成 f2 的参数 “ [1,2],undefined ,undefined ”,执行f2方法后,打印出 [1,2],undefined ,undefined 三个值。

三.apply与call带来的便利

1. push();

push参数是类似(a,b,c,d,e)如此传输的,如果在一个数组的基础上进行传输另一个数组的内容,可以如下:

//apply用法
 var arr = new Array(1,2,3)
 var arr1 = new Array(11,21,31)
 Array.prototype.push.apply(arr,arr1)
 console.log(arr)//[1, 2, 3, 11, 21, 31]
 
 //call用法
 var arr = new Array(1,2,3)
 var arr1 = new Array(11,21,31)
 Array.prototype.push.call(arr,arr1[0],arr1[1],arr1[2])
 console.log(arr)//[1, 2, 3, 11, 21, 31]

2. 数组利用Math求最大和最小值

apply和call的第一个参数,如果是null或者undefined,则apply或call前面的函数会把this指向window

//apply的用法
 var _maxNum = Math.max.apply(null,[1,3,2,4,5])
 console.log(_maxNum)//5
 var _minNum = Math.min.apply(null,[1,3,2,4,5])
 console.log(_minNum)//1
 
 //call的用法
 var _maxNum = Math.max.call(null,1,3,2,4,5)
 console.log(_maxNum)//5
 var _minNum = Math.min.call(null,1,3,2,4,5)
 console.log(_minNum)//1

 四.总结

简而言之,apply和call函数的第一个参数都是用来替换this指向的对象;apply的第二个参数使用arguments或者类似数组的参数进行传参,call的第二个或以上的参数,使用独立单位,一个一个进行传参;执行顺序是apply或call的第一个参数先执行得到结果,然后执行apply或call前面的函数,执行的时候用已经执行的结果所指代的this去执行。apply和call的使用除了参数上的使用方式不同外,功能是一模一样的。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
关于javascript中的typeof和instanceof介绍
Dec 04 Javascript
JavaScript+CSS控制打印格式示例介绍
Jan 07 Javascript
zepto.js中tap事件阻止冒泡的实现方法
Feb 12 Javascript
JavaScript数组前面插入元素的方法
Apr 06 Javascript
JS原型链怎么理解
Jun 27 Javascript
js计算系统当前日期是星期几的方法
Jul 14 Javascript
Vuejs第七篇之Vuejs过渡动画案例全面解析
Sep 05 Javascript
Node.js connect ECONNREFUSED错误解决办法
Sep 15 Javascript
Bootstrap CSS组件之导航(nav)
Dec 17 Javascript
SpringMVC简单整合Angular2的示例
Jul 31 Javascript
vue和react等项目中更简单的实现展开收起更多等效果示例
Feb 22 Javascript
JavaScript的Object.defineProperty详解
Jul 09 Javascript
vue-cli在 history模式下的配置详解
Nov 26 #Javascript
js实现淘宝首页的banner栏效果
Nov 26 #Javascript
JS实现排行榜文字向上滚动轮播效果
Nov 26 #Javascript
vue实现pdf文档在线预览功能
Nov 26 #Javascript
Vue实现商品飞入购物车效果(电商项目)
Nov 26 #Javascript
使用Vue生成动态表单
Nov 26 #Javascript
vue实现在线预览pdf文件和下载(pdf.js)
Nov 26 #Javascript
You might like
php+mysql大量用户登录解决方案分析
2014/12/29 PHP
YII动态模型(动态表名)支持分析
2016/03/29 PHP
如何在PHP中使用AES加密算法加密数据
2020/06/24 PHP
javascript权威指南 学习笔记之javascript数据类型
2011/09/24 Javascript
多浏览器兼容性比较好的复制到剪贴板的js代码
2011/10/09 Javascript
javascript-简单的日历实现及Date对象语法介绍(附图)
2013/05/30 Javascript
JavaSciprt中处理字符串之sup()方法的使用教程
2015/06/08 Javascript
js实现带缓冲效果的仿QQ面板折叠菜单代码
2015/09/06 Javascript
jQuery中的ajax async同步和异步详解
2015/09/29 Javascript
Javascript基础知识盲点总结之函数
2016/05/15 Javascript
bootstrap模态框跳转到当前模板页面 框消失了而背景存在问题的解决方法
2020/11/30 Javascript
Nodejs进阶:express+session实现简易登录身份认证
2017/04/24 NodeJs
jfinal与bootstrap的登出实战详解
2017/11/27 Javascript
在 Angular6 中使用 HTTP 请求服务端数据的步骤详解
2018/08/06 Javascript
vue悬浮可拖拽悬浮按钮的实例代码
2019/08/20 Javascript
ES11新增的这9个新特性,你都掌握了吗
2020/10/15 Javascript
微信小程序实现下拉加载更多商品
2020/12/29 Javascript
微信小程序之高德地图多点路线规划过程示例详解
2021/01/18 Javascript
[46:47]2014 DOTA2国际邀请赛中国区预选赛 DT VS HGT
2014/05/22 DOTA
[26:40]DOTA2上海特级锦标赛A组资格赛#1 Secret VS MVP.Phx第一局
2016/02/25 DOTA
python 连接sqlite及简单操作
2017/06/30 Python
Selenium 模拟浏览器动态加载页面的实现方法
2018/05/16 Python
基于python3实现socket文件传输和校验
2018/07/28 Python
实例详解python函数的对象、函数嵌套、名称空间和作用域
2019/05/31 Python
python socket 聊天室实例代码详解
2019/11/14 Python
python创建ArcGIS shape文件的实现
2019/12/06 Python
Linux开机引导的步骤是什么
2014/02/26 面试题
送温暖献爱心活动总结
2014/07/08 职场文书
建筑学专业自荐书
2014/07/09 职场文书
2015年收银员个人工作总结
2015/04/01 职场文书
2015年机关党委工作总结
2015/05/23 职场文书
婚礼上证婚人致辞
2015/07/28 职场文书
新年寄语2016
2015/08/17 职场文书
CSS预处理框架——Stylus
2021/04/21 HTML / CSS
MongoDB日志切割的三种方式总结
2021/09/15 MongoDB
Java实现简单小画板
2022/06/10 Java/Android