Passing an Array to a Function as a Value in JavaScript

Scott Price
3 min readApr 6, 2018

--

Using Spread Operators and Rest Parameters

Mutating arrays

When you pass an array into a function in JavaScript, it is passed as a reference. Anything you do that alters the array inside the function will also alter the original array. for example this code will log [1, 2, 3] to the console:

var array = [1, 2, 3, 4];const mutate = arr => {
arr.pop();
return arr;
}
mutate(array);console.log(array); // result [1, 2, 3]

copying the passed in array into a new array and doing all your processing on the new array does not help:

var array = [1, 2, 3, 4];const mutate = arr => {
var newArr = arr;
newArr.pop();
return newArr;
}
mutate(array);console.log(array); // result [1, 2, 3] - Still mutated!

This happens because var newArr = arr; does not create a new array. All this does is point a new variable to the same array.

You can use Array.from:

var newArr = Array.from(arr);

or slice():

var newArr = arr.slice();

to copy the array passed into the function into a new array. Than you can change the new array without mutating the original array.

… Another Way …

I was looking at the definition of rest parameters and spread operators this morning and it occurred to me that there is another way to pass an array as a value instead of a reference.

A rest parameter allows us to represent an indefinite number of arguments as an array. When you define a function using a rest parameter, the arguments of the function, no matter how many they are, will be turned into an array.

the spread operator allows an iterable, like an array, to be expanded in place. If you use a spread operator in pass an array into a function call, the function will receive the individual values of the array as arguments.

If we combine these two concepts, by defining our function with a rest parameter and calling the function with a spread operator we can perform operations on the array withing the function with not mutating the original array.

var array = [1, 2, 3, 4];// use rest parameter in function definition
// to turn passed values into array

const noMutate = (…arr) => {
arr.pop();
return arr;
}
// use spread operator in function call to
// turn array elements into function arguments

noMutate(…array);
console.log(array); // result [1, 2, 3, 4]

Passing in other arguments

You can pass other arguments with the rest parameter as long as they come before the rest parameter. For example, you can implement your own version of a filter function that multiplies every element of an array by another number like this:

var arr = [1, 2, 3, 4];const noMutate = (num, …arr) => {
var multiple = []
for(elem of arr) multiple.push(elem * num);
return multiple;
}
var double = noMutate(2, …arr);console.log(double); // returns [2, 4, 6, 8]
console.log(arr); // not mutated: [1, 2, 3, 4]

You can even use the spread operator to pass in properties of a JavaScript object like this:

var obj = {
arr: [1, 2, 3, 4]
};
const noMutate = (num, …arr) => {
console.log(arr);
var multiple = []
for(elem of arr) multiple.push(elem * num);
return multiple;
}
var double = noMutate(2, …obj.arr);console.log(double); // returns [2, 4, 6, 8]
console.log(arr); // not mutated: [1, 2, 3, 4]

Performance wise, I am not sure how this compares to using Array.from() or .slice(), but it does eliminate one line of code and I think it makes your code look cleaner. If anybody knows how this impacts performance, please let me know.

Related Article:

--

--

Scott Price

Front End Developer with Information Security Experience. See my resume and portfolio at www.scottaprice.com