js 关于apply和call的理解使用
关于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
这两行的打印的都是来自 cc._f 方法内的那两句console 。aa的时候算是初始化,里面的 aa._f 方法没有执行。
2.参数为aa.f
这两行的打印的都是来自 cc._f 方法内的那两句console 。aa.f 的时候应该也算是初始化,或者是整个函数当参数传但是不执行这个参数,即 aa._f 方法没有执行。
3.参数为aa.f()
这四行的打印,前面两行来自 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)//
var _minNum = Math.min.apply(null,[1,3,2,4,5])
console.log(_minNum)// //call的用法
var _maxNum = Math.max.call(null,1,3,2,4,5)
console.log(_maxNum)//
var _minNum = Math.min.call(null,1,3,2,4,5)
console.log(_minNum)//
四.总结
简而言之,apply和call函数的第一个参数都是用来替换this指向的对象;apply的第二个参数使用arguments或者类似数组的参数进行传参,call的第二个或以上的参数,使用独立单位,一个一个进行传参;执行顺序是apply或call的第一个参数先执行得到结果,然后执行apply或call前面的函数,执行的时候用已经执行的结果所指代的this去执行。apply和call的使用除了参数上的使用方式不同外,功能是一模一样的。
以上内容纯属个人理解,有误勿喷请指出!谢谢!
js 关于apply和call的理解使用的更多相关文章
- 关于JS中apply方法的基本理解
最近研究OpenLayers源码时,发现其中使用了比较多的apply方法,对其也是很不明白.于是上网经过多方面了解以及自己细细体会后,终于算是基本明白是其干什么的了,这里分享下.apply方法的造型是 ...
- js call apply bind简单的理解
相同点:JS中call与apply方法可以改变某个函数执行的上下文环境,也就是可以改变函数内this的指向.区别:call与apply方法的参数中,第一个参数都是指定的上下文环境或者指定的对象,而ca ...
- 关于JS call apply 对象、对象实例、prototype、Constructor、__proto__
关于call与apply的理解容易让人凌乱,这里有个方法可供参考 tiger.call(fox,arg1,arg2...) tiger.apply(fox,[arg1,arg2...]) 理解为 fo ...
- 原生JS中apply()方法的一个值得注意的用法
今天在学习vue.js的render时,遇到需要重复构造多个同类型对象的问题,在这里发现原生JS中apply()方法的一个特殊的用法: var ary = Array.apply(null, { &q ...
- js中apply方法的使用
js中apply方法的使用 1.对象的继承,一般的做法是复制:Object.extend prototype.js的实现方式是: Object.extend = function(destinat ...
- js中的回调函数的理解和使用方法
js中的回调函数的理解和使用方法 一. 回调函数的作用 js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作,这时候就需要用到回调函数. 二. 回调函数的解释 因为 ...
- JS中的apply,call,bind深入理解
在Javascript中,Function是一种对象.Function对象中的this指向决定于函数被调用的方式.使用apply,call 与 bind 均可以改变函数对象中this的指向,在说区别之 ...
- 学习前端的菜鸡对JS的call,apply,bind的通俗易懂理解
call,apply,bind 在JavaScript中,call.apply和bind是Function对象自带的三个方法,都是为了改变函数体内部 this 的指向. a ...
- js中apply,call的用法
最近一直在用 js 写游戏服务器,我也接触 js 时间不长,大学的时候用 js 做过一个 H3C 的 web的项目,然后在腾讯实习的时候用 js 写过一些奇怪的程序,自己也用 js 写过几个的网站.但 ...
随机推荐
- LeetCode初级算法--设计问题01:Shuffle an Array (打乱数组)
LeetCode初级算法--设计问题01:Shuffle an Array (打乱数组) 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:h ...
- 在树莓派上安装Theano
“查遍全网都没人成功在树莓派安装Theano,这是什么样的感觉?” ——写在开头 在这里必须先说一下,由于安装过程中的坑太多了,遇到的问题层出不穷,所以我这里只能记录我安装过程中的印象深刻的问题,如果 ...
- EFCore--->> CodeFirst (Vs2019 Core3.0)的简单使用
直接上干货 EFCore--->> CodeFirst (Vs2019 Core3.0) 1: 安装下面3个对应的package(在Nuget控制台或者直接NuGet包查询点击下载,我喜欢 ...
- 设计模式(十七)Observer模式
在Observer模式中,当观察对象的状态发生变化时,会通知给观察者.Observer模式适用于根据对象状态进行相应处理的场景. 首先看一下示例程序的视图. 然后用实际代码来理解这种设计模式. pac ...
- Redis(五)持久化
一.RDB RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发. 1.触发机制 (1)手动触发:save命令和bgsave命令 save命令:阻塞当前Re ...
- C# .NET .NET Framework .NET CORE 等的关系简介
2019新的一年,祝大家新年快乐,工作生活一帆风顺,心想事成!诸事大吉! 这篇文章是我今年的第一篇博客,主题是:C# .NET .NET Framework .NET CORE 等这些名词之 ...
- 设计模式C++描述----14.外观(Facade)模式
一. 举例说明 还以我以前做的文件系统(FileSys)为例: 文件系统是一个独立的系统,它提供一套核心的文件操作. 除了文件系统,还有四个子系统,分别是杀毒子系统(KillVirus),压缩子系统( ...
- egg-sequelize --- nodejs
项目 egg + sequelize + mysql2 项目结构 配置 安装模块 npm install --save egg-sequelize npm install --save egg-cor ...
- Educational Codeforces Round 71 (Rated for Div. 2)E. XOR Guessing
一道容斥题 如果直接做就是找到所有出现过递减的不同排列,当时硬钢到自闭,然后在凯妹毁人不倦的教导下想到可以容斥做,就是:所有的排列设为a,只考虑第一个非递减设为b,第二个非递减设为c+两个都非递减的情 ...
- Java自动化测试框架-09 - TestNG之依赖注入篇 (详细教程)
1.-依赖注入 TestNG支持两种不同类型的依赖项注入:本机(由TestNG本身执行)和外部(由诸如Guice的依赖项注入框架执行). 1.1-本机依赖项注入 TestNG允许您在方法中声明其他参数 ...