6

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);
        }
    };
}
1
  • 3
    i believe so. As rest params create a simple array, i think it is optimizable Commented Jul 26, 2017 at 17:40

1 Answer 1

7

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.

Strict mode fixes it all

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 is arg, setting arg also sets arguments[0], and vice versa (unless no arguments were provided or arguments[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 corresponding arguments[i].

Sign up to request clarification or add additional context in comments.

2 Comments

Don't forget that strict mode fixes it all. It's just the weirdness of an array-like object (instead of a real array) then.
@Bergi, indeed, snippet added to illustrate that. Thanks!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.