更简单的理解 apply , call

2018-12-07 admin

The first time I know apply was when I met this code:

Math.max.apply(null, [1, 2, 3, 4])

As the mdn said,

The apply() method calls a function with a given this value, and arguments provided as an array (or an array-like object).

Note: While the syntax of this function is almost identical to that of call(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments.

Actually, in case above, thisArg has no influence which means code below also works:

Math.max.apply(undefined, [1, 2, 3, 4])
Math.max.apply(Math, [1, 2, 3, 4])

The only effect of apply in the code above is that it can pass the values in array to the function max. So, code above equal

Math.max(1, 2, 3, 4)

Why would I mention this? Because we don’t need this anymore because we already have ... which works like:

Math.max(...[1, 2, 3, 4])

The reason that we still need apply and call is the thisArg. They can help us call some powerful methods.

thisArg in apply and call

I guess you might have seen this code:

Array.prototype.slice.call({ length: 2 })
function fn() {
  console.log(Array.prototype.slice.call(arguments))
}
fn(1, 2, 3, 4) //[1,2,3,4]

Today, we don’t need this either because of Array.from. But I still want to talk about it for explanation. In the case above, call was used because we want to do something like:

let obj = { length: 2 }
obj.slice() //Uncaught TypeError: obj.slice is not a function

It would cause error because slice was defined in Array.prototype. Only Array instance can call that method. But actually in the implementation of slice, it doesn’t need to be called by Array instance and there is a lot of methods like this. So, in this case, call or apply would let non Array instance call these methods which means

Array.prototype.slice.call({ length: 2 })
//help you do
let obj = { length: 2 }
obj.slice = Array.prototype.slice
obj.slice()

And to help it easier to understand , you can remember it like:

method.call(thisArg, ...args)
//works like in most cases
thisArg.method = method
thisArg.method(...args)
//for apply
method.apply(thisArg, args)
//works like in most cases
thisArg.method = method
thisArg.method(...args)

Wasn’t that easy ?

So, let get back to Math.max.apply({}, [1, 2, 3, 4]). You can remember it like:

let thisArg = {}
thisArg.max = Math.max
thisArg.max(...[1, 2, 3, 4])

And more cases:

Object.prototype.toString.call([]) //"[object Array]"
//help you do this
let thisArg = []
thisArg.toString = Object.prototype.toString
thisArg.toString() //"[object Array]"
//while
[].toString()//""

Or

;[' sd ', 1, 3].map(Function.prototype.call, String.prototype.trim) //['sd','1','3']
//help you do
;[' sd ', 1, 3].map(function(...args) {
  return String.prototype.trim.call(...args)
})
//help you do
;[' sd ', 1, 3].map(function(...args) {
  let thisArg = args[0]
  thisArg.trim = String.prototype.trim
  return thisArg.trim(...args.slice(1)) //Uncaught TypeError: thisArg.trim is not a function
})

In the case above, it will got error because args[0] is Primitive values. You can’t call methods in Primitive values. But it can still help you understand.

More in apply

As apply can accept an array-like object. So, what would happen if coding like:

Array.apply(null, { length: 2 })

Actually, it equals

Array.apply(null, [undefined, undefined])

So, you can understand it like:

let thisArg = {} //set null would get error in code below, also thisArg in above case is not important
thisArg.Array = Array
thisArg.Array(undefined, undefined)

Hope it’s easier to understand apply and call.

Original Post

原文链接:https://segmentfault.com/a/1190000017257214

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-47476.html

文章标题:更简单的理解 apply , call

相关文章
angular+ionic 的app上拉加载更新数据实现方法
第一步,首先需要在<ion-content>标签里面加入标签<ion-infinite-scroll ng-if="hasmore" on-infinite="loadMore()"...
2017-03-07
js实现简单的可切换选项卡效果
本文实例讲述了js实现简单的可切换选项卡效果的方法。分享给大家供大家参考。具体如下: 如图,最简单的纯粹的选项卡 第一步,当然是先写html代码和css样式 <!DOCTYPE html> <html> <h...
2017-03-22
使用JavaScript制作一个简单的计数器的方法
设计思想 该方法的关键是Cookie技术和动态图像特性的综合运用。使用Cookie,可以在用户端的硬盘上记录用户的数据,下次访问此站点时,即可读取用户端硬盘的Cookie,直接得知来访者的身份和访问次数等有关信息。JavaScript中通过...
2017-03-27
深入理解JavaScript的React框架的原理
如果你在两个月前问我对React的看法,我很可能这样说: 我的模板在哪里?javascript中的HTML在做些什么疯狂的事情?JSX开起来非常奇怪!快向它开火,消灭它吧! 那是因为我没有理解它. 我发誓,React 无疑是在正确的轨道...
2017-03-26
使用HTML+CSS+JS制作简单的网页菜单界面
写ABROAD项目用到了标签这个东东,其实标签在WEB上到处可见,图中就依次显示了DCC文章发布器、ABROAD后台添加数据、百度图片搜索、sf发布博客文章时贴标签的样式——标签就像浏览器里原生的checkbox一样,不过checkbox实...
2017-03-27
JavaScript实现滑动到页面底部自动加载更多功能
话不多说,请看代码: //滚动条到页面底部加载更多案例 $(window).scroll(function(){ var scrollTop = $(this).scrollTop(); /&#x2F...
2017-03-17
关于js里的this关键字的理解
this关键字在c++,java中都提供了这个关键字,在刚开始学习时觉得有难度,但是只要理解了,用起来就方便多了,下面通过本篇文章给大家详解js里this关键字的理解。 关于this,是很多前端面试必考的题目,有时候在网上看到这些题目,自己...
2017-03-29
深入理解JavaScript编程中的原型概念
JavaScript 的原型对象总是让人纠结。即使是经验丰富的JavaScript专家甚至其作者,经常对这一概念给出很有限的解释。我相信问题来自于我们对原型最早的认识。原型总是与new, constructor 以及令人困惑的prototy...
2017-03-25
vue-video-player 更改视频源
背景:根据用户的信息来显示不同的视频源 <template> <div class="video-box-wrap" v-show="video.show"> ...
2018-05-05
10条建议帮助你创建更好的jQuery插件
本文总结了帮助你创建更好jQuery插件的10条建议。分享给大家供大家参考。具体说明如下: 在开发过很多 jQuery 插件以后,我慢慢的摸索出了一套开发jQuery插件比较标准的结构和模式。这样我就可以 copy & paste ...
2017-03-23
回到顶部