The Managing arguments
section in Bluebird's article on Optimization killers states that:
The
arguments
object must not be passed or leaked anywhere.
In other words, don't do the following:
function leaky(){
return arguments;
}
But do do this:
function not_leaky(){
var i = arguments.length,
args = [];
while(i--) args[i] = arguments[i];
return args;
}
With the introduction of Rest paramters, will passing the rest parameter array still cause optimization issues? From what I am understanding, the issue is that we can't let the actual arguments
Object get loose. Finite, defined copies of arguments
are OK, but not the actual Object itself. If that is the case, is the rest argument treated as an OK and optimizable copy of arguments
when used in the following way?
function maybe_optimizable(...args){
return args;
}
Specifically, I'm trying to write a debounce
function based on David Walsh's debounce
function (which is based on Underscore.js') and I believe there is an issue with assigning arguments
to a variable within the top scope of the debounce
function. To rectify this I wrote the following:
function debounce(func, wait, immediate) {
let timeout;
return function (...args) {
let context = this,
now = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(() => {
timeout = null;
if (!immediate) {
func.apply(context, args);
}
}, wait);
if (now) {
func.apply(context, args);
}
};
}
The rest parameter syntax allows a function to accept an indefinite number of arguments as an array, providing a way to represent variadic functions in JavaScript.
Note: The rest parameter have to be the last argument, as its job is to collect all the remaining arguments into an array. So having a function definition like the code below doesn't make any sense and will throw an error.
Rest parameters represent the unknown number of arguments inside the function, whereas the arguments object represents all arguments passed to the function.
The main difference between rest and spread is that the rest operator puts the rest of some specific user-supplied values into a JavaScript array. But the spread syntax expands iterables into individual elements.
One of the challenges with the arguments
object, is that it needs to be a live collection of the parameters values, even when they are reassigned. See how even a (parameter) variable with a primitive value gets changed without any explicit assignment to it, and it happens outside of the function:
function modify(arr) {
arr[0] = 3;
}
(function (a) {
console.log('arguments is an ' + arguments.constructor.name);
console.log('a is ', a);
modify(arguments);
console.log('after calling modify, a is ', a);
})(0);
See this blog for more on such behaviour.
One can imagine that code optimisation becomes a nightmare when such an object travels around, never losing such magical capabilities.
This of course, does not happen with a normal array, and the array you get with the spread syntax is indeed a normal array:
(function (...args) {
console.log('args is an ' + args.constructor.name);
})(0);
You can rest (no pun intended) assured that the mentioned code optimisation problems with arguments
do not apply to ...args
.
As Bergi mentioned. The live semantic of arguments
is no longer there when the function, whose arguments
variable is used, is written in strict mode JavaScript:
function modify(arr) {
arr[0] = 3;
}
(function (a) {
"use strict"; // <-----
console.log('In strict mode');
console.log('arguments is still an ' + arguments.constructor.name);
console.log('a is ', a);
modify(arguments);
console.log('after calling modify, a is still ', a);
})(0);
As stated in mdn's article on strict mode:
strict mode code doesn't alias properties of
arguments
objects created within it. In normal code within a function whose first argument isarg
, settingarg
also setsarguments[0]
, and vice versa (unless no arguments were provided orarguments[0]
is deleted).arguments
objects for strict mode functions store the original arguments when the function was invoked.arguments[i]
does not track the value of the corresponding named argument, nor does a named argument track the value in the correspondingarguments[i]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With