The first time I know apply
was when I met this code:
Math.max.apply(null, [1, 2, 3, 4])
As the mdn shows, the syntax is:
function.apply( thisArg , [argsArray] )
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
.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。