What's the clearest way to indicate a function uses the 'arguments' object?

此生再无相见时 提交于 2019-12-22 09:25:47

问题


What's the best way to indicate a function uses the 'arguments' object?
This is obviously opinion based but are there any conventions? When would it be better to use an array of arguments?

Some examples:

// Function takes n arguments and makes them pretty.
function manyArgs() {
    for (var i = 0; i < arguments.length; i++)
    console.log(arguments[i]);
}

function manyArgs( /* n1 , n2, ... */ )

function manyArgs(n1 /*, n2, ... */ )

function manyArgs(argArray)

回答1:


// Using ES6 syntax ...
var foo = function(/*...args*/){
    // shim Array.from, then
    var args = Array.from(arguments);
    // or
    var args = [].slice.call(arguments);
};



回答2:


I never use variadic arguments in JavaScript. There are many better ways of structuring your code. For example, I would rewrite your code as follows:

[1,2,3,4,5].forEach(log); // instead of manyArgs(1,2,3,4,5);

function log(a) {
    console.log(a);
}

It's clear and concise.

Another example, if you want to find the sum of a list of numbers in JavaScript:

[1,2,3,4,5].reduce(add, 0); // instead of add(1,2,3,4,5);

function add(a, b) {
    return a + b;
}

There are so many useful abstractions available to structure your code that I don't see the benefit of using variadic arguments at all.

I do however use the arguments object for default values:

function foo(a,b,c) {
    switch (arguments.length) {
    case 0: a = "default argument for a";
    case 1: b = "default argument for b";
    case 2: c = "default argument for c";
    }

    // do something with a, b & c
}

Hence my advise to you would be to not use variadic arguments at all. Find a better abstraction for your code. I've never encountered the need to use variadic arguments in the 8 years that I have been programming in JavaScript.


Edit: I would advocate using a more functional approach to writing code. We can use currying to make code more succinct:

function curry(func, length, args) {
    switch (arguments.length) {
    case 1: length = func.length;
    case 2: args = [];
    }

    var slice = args.slice;

    return function () {
        var len = arguments.length;
        var a = args.concat(slice.call(arguments));
        if (len >= length) return func.apply(this, a);
        return curry(func, length - len, a);
    };
}

Using curry we can rewrite the sum example as follows:

var reduce = curry(function (func, acc, a) {
    var index = 0, length = a.length;
    while (index < length) acc = func(acc, a[index++]);
    return acc;
});

var sum = reduce(add, 0);

sum([1,2,3,4,5]); // instead of add(1,2,3,4,5);

function add(a, b) {
    return a + b;
}

Similarly for Math.max and Array.prototype.concat:

var reduce1 = curry(function (func, a) {
    if (a.length === 0)
        throw new Error("Reducing empty array.");
    return reduce(func, a[0], a.slice(1));
});

var maximum = reduce1(max);

maximum([1,2,3,4,5]); // instead of Math.max(1,2,3,4,5);

function max(a, b) {
    return a > b ? a : b;
}

var concat = reduce(function (a, b) {
    return a.concat(b);
}, []);

concat([[1,2],[3,4],[5,6]]) // instead of [1,2].concat([3,4],[5,6])

As for Array.prototype.push, because it mutates the input array instead of creating a new one, I prefer using array.concat([element]) instead of array.push(element):

var push = reduce(function (a, e) {
    return a.concat([e]);
});

push([1,2,3], [4,5]); // instead of [1,2,3].push(4, 5)

So what are the advantages of writing code this way:

  1. Currying is awesome. It allows you to create new functions from old ones.
  2. Instead of using variadic arguments you are passing arrays to functions. So you don't need any special way to indicate that the function uses arguments.
  3. Suppose you have to find the sum of an array named array. Using this method you just do sum(array). If you use variadic arguments then you would need to do add.apply(null, array).
  4. Suppose you want to find the sum of a, b & c. All you need to do is sum([a,b,c]), as compared to add(a, b, c). You need to put in the extra [] brackets. However doing so makes your code more understandable. According to the zen of python “explicit is better than implicit”.

So these are some of the reasons I never use variadic arguments in my programs.




回答3:


The clearest way is to use the spread operator available in ES6, CoffeeScript (where they are called "splats" and the three dots come after the identifer), and TypeScript (where they are called "rest parameters").

// Function takes n arguments and makes them pretty.
function manyArgs(...args) {
    for (var i = 0; i < args.length; i++)
        console.log(args[i]);
}

If you're in an environment where you can use them, of course. It is both better self-documenting, and avoids having to muck around with arguments.



来源:https://stackoverflow.com/questions/26700711/whats-the-clearest-way-to-indicate-a-function-uses-the-arguments-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!