指示函数使用'参数'的最明确方式是什么?宾语?

时间:2014-11-02 15:03:11

标签: javascript conventions

指示某个功能使用'参数'的最佳方式是什么?反对呢?
这显然是基于意见的,但有没有任何约定?什么时候使用一组参数会更好?

一些例子:

// 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)

3 个答案:

答案 0 :(得分:4)

我从不在JavaScript中使用可变参数。有许多更好的方法来构建代码。例如,我会按如下方式重写您的代码:

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

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

它清晰简洁。

另一个例子,如果你想在JavaScript中找到一个数字列表的总和:

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

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

有很多有用的抽象可用于构造代码,我根本没有看到使用可变参数的好处。

但我使用arguments对象作为默认值:

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
}

因此我建议你不要使用可变参数。为代码找到更好的抽象。我在用JavaScript编程的8年里从未遇到过使用可变参数的需要。


编辑:我主张使用更实用的方法来编写代码。我们可以使用currying使代码更简洁:

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);
    };
}

使用curry我们可以按如下方式重写sum示例:

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;
}

同样适用于Math.maxArray.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])

对于Array.prototype.push,因为它改变了输入数组而不是创建新数组,所以我更喜欢使用array.concat([element])而不是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)

那么以这种方式编写代码有什么好处:

  1. Currying很棒。它允许您从旧的功能创建新功能。
  2. 您将数组传递给函数,而不是使用可变参数。因此,您不需要任何特殊方式来指示该函数使用arguments
  3. 假设您必须找到名为array的数组的总和。使用此方法,您只需执行sum(array)。如果使用可变参数,则需要执行add.apply(null, array)
  4. 假设您要查找ab&amp;的总和。 c。与sum([a,b,c])相比,您需要做的只是add(a, b, c)。您需要输入额外的[]括号。但这样做会使您的代码更容易理解。根据{{​​3}} “显式优于隐式”
  5. 所以这些是我从未在我的程序中使用可变参数的一些原因。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

最明确的方法是使用ES6CoffeeScript中可用的点差运算符(它们被称为&#34; splats&#34;三个点位于标识符之后),{ {3}}(称为&#34;休息参数&#34;)。

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

当然,如果您处于可以使用它们的环境中。它既可以更好地自我记录,又可以避免不得不使用arguments