Passing Arrays as Function Arguments

Samantha Ming on February 18, 2019

If you want to pass an array into a variadic function. You can use ES6 spread to turn that array into a list of arguments. Yay, so much cleaner a... [Read Full]
markdown guide
 

TIL function.prototype.apply(). I was looking at your "old way" and thinking, what is she talking about? :)

I guess in Javascript whenever I've wanted to pass in an array it's always been to a function that accepts arrays. I've seen people talk about the spread operator but for functions I'd expect the need to be the other way around (as with C-like functions like printf(), where you'd probably never want to convert an array to a series of parameters)

 

Funny thing that functions like Math.Max internally receive that arguments as arrays (or array-like objects to be precise)

 

“Array-like”, that’s the keyword. I remember I was so confused when I first encountered that 😅

 

Good ol' this.arguments. My favorite Javascript feature that I'm afraid to use because it doesn't have all the Array methods I want.

 

AFAIK it causes deoptimization, while (...args) works much better.
Still, if you expect a real array, like in Math's case, you should just take an array.

Math.max(...new Array(200000).fill(1))
Math.max.apply(undefined,new Array(200000).fill(1))

These both fail with a stack overflow, and the only way to get an answer is to implement it yourself:

new Array(20000000).fill(1).reduce((a,b)=>b>a?b:a)
 

It looks like an array, but unfortunately, it isnt :(

Actually, maybe I should write a post about that. The arguments is an interesting topic and I don't think everyone knows that exists 🤔 Even if they knew, the post will be a nice reminder 😂

@samanthaming if you end up writing a post on it, I beg of you to include warnings about performance and analysis implications, as well as the "single rest argument"((...args)) alternative.
Honestly, that's the only way I see to offset the damage of more people finding out about/remembering it :D

 

Do you feel that variadic functions should be used?
Or would you prefer if there were only fixed-length functions, eg if Math.max was split into:

Math.max2 = (a, b) => Math.max(a, b)
Math.maxA = arr => Math.max(...arr)
 

This is problematic because it goes on the stack.

const bite1 = arr => {
  const [head, ...tail] = arr
  if (tail.length === 0) return "⚰"
  return bite1(tail)
}
console.log(bite1(new Array(2000))) // Success

const biteV = (...args) => {
  const [head, ...tail] = args
  if (tail.length === 0) return "⚰"
  return biteV(...tail)
}
console.log(biteV(...new Array(600))) // DIES

In both cases we are iterating immutably and using lots of memory, but the second runs out of stack space while the first doesn't. (And mere 600 is far from a ridiculous number!)

 

The Spread Power!

Thank you, Samantha. This is a useful post! 👍

 

Awesome! Glad to hear that, thank you for reading the post :D

 

not bad, but i believe, it's so unpredictable this way.

 

Variadic variableness :-) Thanks, Samantha! Appreciate you explaining this so well :-)

code of conduct - report abuse