Javascript Terms/Concepts
Rest parameters ...
A function can be called with any number of arguments, no matter how it is defined.
function sum(a, b) {
return a + b;
}
// will not error due to “excessive” arguments
alert( sum(1, 2, 3, 4, 5) ); // 3 - only the first 2 arguments are being used in the function
The rest of the parameters can be included in the function definition by using three dots ... followed by the name of the array that will contain them.
The dots literally mean “gather the remaining parameters into an array”.
function sumAll(...args) { // args is the name for the array
let sum = 0;
for (let arg of args) sum += arg;
return sum;
}
alert( sumAll(1) ); // 1
alert( sumAll(1, 2) ); // 3
alert( sumAll(1, 2, 3) ); // 6
We can choose to get the first parameters as variables, and gather only the rest.
function showName(firstName, lastName, ...titles) {
alert( firstName + ' ' + lastName ); // Julius Caesar
// the rest go into titles array
// i.e. titles = ["Consul", "Imperator"]
alert( titles[0] ); // Consul
alert( titles[1] ); // Imperator
alert( titles.length ); // 2
}
showName("Julius", "Caesar", "Consul", "Imperator");
The rest parameters must be at the end The rest parameters gather all remaining arguments, so the following does not make sense and causes an error:
function f(arg1, ...rest, arg2) { // arg2 after ...rest ?!
// error
}
The “arguments” variable
There is also a special array-like object named arguments that contains all arguments by their index.
function showName() {
alert( arguments.length );
alert( arguments[0] );
alert( arguments[1] );
// it's iterable
// for(let arg of arguments) alert(arg);
}
// shows: 2, Julius, Caesar
showName("Julius", "Caesar");
// shows: 1, Ilya, undefined (no second argument)
showName("Ilya");
In old times, rest parameters did not exist in the language, and using arguments was the only way to get all arguments of the function.
But the downside is that although arguments is both array-like and iterable, it’s not an array. It does not support array methods, so we can’t call arguments.map(...)
for example.
Also, it always contains all arguments. We can’t capture them partially, like we did with rest parameters.
So when we need these features, then rest parameters are preferred.
Arrow functions do not have "arguments" If we access the arguments object from an arrow function, it takes them from the outer “normal” function.
function f() {
let showArg = () => alert(arguments[0]);
showArg();
}
f(1); // 1
As we remember, arrow functions don’t have their own this. Now we know they don’t have the special arguments object either.
Spread syntax
When ...arr
is used in the function call, it “expands” an iterable object arr into the list of arguments.
let arr = [3, 5, 1];
let arr2 = [8, 3, -8, 1];
console.log( Math.max(...arr) ); // spread turns array into a list of arguments
console.log( Math.max(...arr, ...arr2) ); // can pass multiple iterables this way
console.log( Math.max(1, ...arr1, 2, ...arr2, 25) ); // can even combine the spread syntax with normal values
let merged = [0, ...arr, 2, ...arr2]; // spread syntax used to merge arrays
// used on strings
let str = "Hello";
console.log( [...str] ); // H,e,l,l,o
Copy and array/object
Array
let arr = [1, 2, 3];
let arrCopy = [...arr]; // spread the array into a list of parameters
// then put the result into a new array
// do the arrays have the same contents?
alert(JSON.stringify(arr) === JSON.stringify(arrCopy)); // true
// are the arrays equal?
alert(arr === arrCopy); // false (not same reference)
// modifying our initial array does not modify the copy:
arr.push(4);
alert(arr); // 1, 2, 3, 4
alert(arrCopy); // 1, 2, 3
Object
let obj = { a: 1, b: 2, c: 3 };
let objCopy = { ...obj }; // spread the object into a list of parameters
// then return the result in a new object
// do the objects have the same contents?
alert(JSON.stringify(obj) === JSON.stringify(objCopy)); // true
// are the objects equal?
alert(obj === objCopy); // false (not same reference)
// modifying our initial object does not modify the copy:
obj.d = 4;
alert(JSON.stringify(obj)); // {"a":1,"b":2,"c":3,"d":4}
alert(JSON.stringify(objCopy)); // {"a":1,"b":2,"c":3}