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 添加和移除函数的通用方法
Oct 20 Javascript
定时器(setTimeout/setInterval)调用带参函数失效解决方法
Mar 26 Javascript
select标签模拟/美化方法采用JS外挂式插件
Apr 01 Javascript
解决IE6的PNG透明JS插件使用介绍
Apr 17 Javascript
不要使用jQuery触发原生事件的方法
Mar 03 Javascript
基于BootStrap Metronic开发框架经验小结【六】对话框及提示框的处理和优化
May 12 Javascript
jQuery+Pdo编写login登陆界面
Aug 01 Javascript
js实现自定义进度条效果
Mar 15 Javascript
JS实现静态页面搜索并高亮显示功能完整示例
Sep 19 Javascript
初试vue-cli使用HBuilderx打包app的坑
Jul 17 Javascript
js实现页面图片消除效果
Mar 24 Javascript
vue使用video插件vue-video-player详解
Oct 23 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函数的实现原理及性能分析(一)
2015/05/13 PHP
PHP实现原生态图片上传封装类方法
2016/11/08 PHP
让人期待的2011年度最佳 jQuery 插件分享
2012/03/16 Javascript
jquery animate实现鼠标放上去显示离开隐藏效果
2013/07/21 Javascript
利用jQuery实现可输入搜索文字的下拉框
2013/10/23 Javascript
div浮层,滚动条移动,位置保持不变的4种方法汇总
2013/12/11 Javascript
JS+CSS实现的竖向简洁折叠菜单效果代码
2015/10/22 Javascript
angularjs 源码解析之scope
2016/08/22 Javascript
jQuery Validate验证框架详解(推荐)
2016/12/17 Javascript
JS生成一维码(条形码)功能示例
2017/01/19 Javascript
完美解决jQuery的hover事件在IE中不停闪动的问题
2017/02/10 Javascript
JS查找数组中重复元素的方法详解
2017/06/14 Javascript
Vue加载json文件的方法简单示例
2019/01/28 Javascript
es6函数之严格模式用法实例分析
2020/03/17 Javascript
vue-cli4项目开启eslint保存时自动格式问题
2020/07/13 Javascript
在vue中axios设置timeout超时的操作
2020/09/04 Javascript
微信小程序实现转盘抽奖
2020/09/21 Javascript
使用vue编写h5公众号跳转小程序的实现代码
2020/11/27 Vue.js
python str与repr的区别
2013/03/23 Python
使用Python编写简单的画图板程序的示例教程
2015/12/08 Python
Python自动发邮件脚本
2017/03/31 Python
Python面向对象编程之继承与多态详解
2018/01/16 Python
基于Python实现定时自动给微信好友发送天气预报
2018/10/25 Python
Django 迁移、操作数据库的方法
2019/08/02 Python
Python实现电视里的5毛特效实例代码详解
2020/05/15 Python
一款基于css3麻将筛子3D翻转特效的实例教程
2014/12/31 HTML / CSS
NBA欧洲商店(英国):NBA Europe Store UK
2018/07/27 全球购物
销售员个人求职的自我评价
2014/02/10 职场文书
毕业大学生自荐信
2014/06/17 职场文书
2014年便民服务中心工作总结
2014/12/20 职场文书
商务代表岗位职责
2015/02/15 职场文书
党支部评议意见
2015/06/02 职场文书
利用python Pandas实现批量拆分Excel与合并Excel
2021/05/23 Python
一文搞懂php的垃圾回收机制
2021/06/18 PHP
漫画《尖帽子的魔法工坊》宣布动画化
2022/04/06 日漫
Nginx开源可视化配置工具NginxConfig使用教程
2022/06/21 Servers