关于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的理解使用的更多相关文章

  1. 关于JS中apply方法的基本理解

    最近研究OpenLayers源码时,发现其中使用了比较多的apply方法,对其也是很不明白.于是上网经过多方面了解以及自己细细体会后,终于算是基本明白是其干什么的了,这里分享下.apply方法的造型是 ...

  2. js call apply bind简单的理解

    相同点:JS中call与apply方法可以改变某个函数执行的上下文环境,也就是可以改变函数内this的指向.区别:call与apply方法的参数中,第一个参数都是指定的上下文环境或者指定的对象,而ca ...

  3. 关于JS call apply 对象、对象实例、prototype、Constructor、__proto__

    关于call与apply的理解容易让人凌乱,这里有个方法可供参考 tiger.call(fox,arg1,arg2...) tiger.apply(fox,[arg1,arg2...]) 理解为 fo ...

  4. 原生JS中apply()方法的一个值得注意的用法

    今天在学习vue.js的render时,遇到需要重复构造多个同类型对象的问题,在这里发现原生JS中apply()方法的一个特殊的用法: var ary = Array.apply(null, { &q ...

  5. js中apply方法的使用

    js中apply方法的使用   1.对象的继承,一般的做法是复制:Object.extend prototype.js的实现方式是: Object.extend = function(destinat ...

  6. js中的回调函数的理解和使用方法

    js中的回调函数的理解和使用方法 一. 回调函数的作用 js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作,这时候就需要用到回调函数. 二. 回调函数的解释 因为 ...

  7. JS中的apply,call,bind深入理解

    在Javascript中,Function是一种对象.Function对象中的this指向决定于函数被调用的方式.使用apply,call 与 bind 均可以改变函数对象中this的指向,在说区别之 ...

  8. 学习前端的菜鸡对JS的call,apply,bind的通俗易懂理解

       call,apply,bind 在JavaScript中,call.apply和bind是Function对象自带的三个方法,都是为了改变函数体内部 this 的指向.            a ...

  9. js中apply,call的用法

    最近一直在用 js 写游戏服务器,我也接触 js 时间不长,大学的时候用 js 做过一个 H3C 的 web的项目,然后在腾讯实习的时候用 js 写过一些奇怪的程序,自己也用 js 写过几个的网站.但 ...

随机推荐

  1. 题解 CF600E 【Lomsat gelral】

    没有多少人用莫队做吗? 蒟蒻水一波莫队 这是一道树上莫队好题. 时间复杂度(\(n\sqrt{n}logn\)) 蒟蒻过菜,不会去掉logn的做法qaq 思路很简单: 1.dfs跑一下树上点的dfs序 ...

  2. JVM 启动调优总结

    启动命令 格式: java -jar 命令行参数 jar包路径 .示例如下 java -Dfile.encoding=utf-8 -jar -XX:MetaspaceSize=128m -XX:Max ...

  3. Spring Cloud ---- 服务注册与发现(Eureka 找到了!找到了! 嘻嘻)

    记录一下吧,为什么接触分布式.因为裸辞之后没有找到工作,好的公司都要求有分布式经验,但是我完全没有.在一次面试的时候,面试官说如果你会分布式架构的话,我可以把工资给你开高2.5,我就考虑着给我点时间, ...

  4. day07整理(内置方法\循环判断)

    目录 一.上节课回顾 (一)if判断 1.单分支结构 2.双分支结构 3.多分支结构 (二)for循环 1.for + break 2.for + continue 3.for循环嵌套 (三)robu ...

  5. fenby C语言 P33

    #include <stdio.h> int main(void){ char *ps="my dream is to be a programmer"; printf ...

  6. SpringBoot系列之@Value和@ConfigurationProperties

    继上一篇博客SpringBoot系列之YAML配置用法之后,再写一篇@Value.@ConfigurationProperties的对比博客 这两个主键都是可以获取配置文件属性的,不过是有比较大的区别 ...

  7. Apache中Cookie长度的设置 414 request-uri too large apache

    起因: 今天在调试Ucenter的同步登陆和同步登出的过程中,浏览器突然出现以下错误提示: Your browser sent a request that this server could not ...

  8. Stringbuilder常用方法

    一.创建Stringbuilder对象StringBuilder strB = new StringBuilder(); 1.append(String str)/append(Char c):字符串 ...

  9. Java面试官最爱问的volatile关键字

    在Java的面试当中,面试官最爱问的就是volatile关键字相关的问题.经过多次面试之后,你是否思考过,为什么他们那么爱问volatile关键字相关的问题?而对于你,如果作为面试官,是否也会考虑采用 ...

  10. 单点登录 - OAuth 2.0 授权码模式(一)

    OAuth 2.0定义了四种授权方式 授权码模式(authorization code) 简化模式(implicit) 密码模式(resource owner password credentials ...