【问题标题】:How come for(var i in arguments) doesn't work?为什么 for(var i in arguments) 不起作用?
【发布时间】:2013-07-15 09:47:03
【问题描述】:

我是 JavaScript 新手。我试图弄清楚为什么这不起作用:

function myFunction(){
    document.getElementById("result").value=add(1,2);
}
function add(){
    var sum = 0;
    for(var i in arguments)
        sum += i;
    return sum;
}

这会输出001。为什么?

【问题讨论】:

  • @SurrealDreams 这有什么关系?请尽量保持建设性。
  • 没有作业,刚接触javascript
  • 只是问,尽管是厚脸皮。我倾向于根据受众来构建不同的答案。

标签: javascript loops arguments key-value


【解决方案1】:

您正在迭代键,请执行以下操作:

function add(){
    var sum = 0;
    for(var i in arguments)
        sum += arguments[i];
    return sum;
}

更具体地说,键是字符串,"0""1",因此您的响应是初始 0 和后续键的串联。

另外,如果你对现代平台上的javascript感兴趣,下面的内容非常清晰简洁。

function add(){
    return [].reduce.call(arguments, function(a, b) {
        return a+b;
    });
}
console.log(add(1,2));

【讨论】:

  • @Justin984:最好使用for (var i = 0; i < arguments.length; i++),因为for (var i in arguments 将迭代arguments 的所有属性,而不仅仅是索引。
  • @tjameson 你能举个例子说明什么地方会出错吗?我不确定迭代所有属性是什么意思。
  • @matt3141 感谢您对此的解释,不幸的是,对于第二个示例,我有点太绿了,还没有多大意义:P
  • @Justin984 我鼓励你看看Array#reduceArray#map等。你可能会找到一篇很好的文章,将它们标记为“函数式JavaScript”组
  • @tjameson 如果我没记错的话,arguments 对象也有一个原型链,它继承自 Object.prototype。
【解决方案2】:

试试这个:

function add(){
    var sum = 0, x = 0;
    for(var i in arguments){
        //the key is an index
        if(!arguments.hasOwnProperty(i)) continue;

        // try converting argument[i] to a number
        x = +arguments[i];

        // check if argument is a valid number 
        if(!isNaN(x)) {
            sum += x;
        }
    }
    return sum;
}

演示: http://jsfiddle.net/vg4Nq/

【讨论】:

  • 这里不需要parseInt
  • 为什么会这样:typeof x != typeof NaNtypeof NaN 将始终为"number"typeof x 也将始终为"number",因此永远不会满足条件。
  • @matt3141 感谢您的更新。此外,我已经将hasOwnProperty 的检查移到parseInt 之前,因为我们已经访问了arguments[i]
  • @TheVillageIdiot 请记住将基数参数提供给parseInt。检查if(isNaN(x)) 意味着您正在检查x不是 一个数字...所以你需要添加!。我两个都加了。希望没关系并且是正确的:)
  • @TheVillageIdiot 我也刚刚更新为实际转换为数字(不解析它......这可能会出现问题,比如值“5p”以某种方式传递),并添加了一个演示跨度>
【解决方案3】:

这是另一种可能性。

function add() {
    var numbers = [].slice.call(arguments),
        sum = 0;

    do {
        sum += numbers.shift();
    } while (isFinite(sum) && numbers.length);

    return +sum;
}

console.log(add(1, 2, 3, 4, 5));

开启jsfiddle

更新:这比reduce 更加跨浏览器。如果我们希望对数据进行更多检查,我们也可以对此进行改进。

function add1() {
    var numbers = [].slice.call(arguments),
        sum = 0,
        x;

    do {
        x = numbers.shift();
        sum += (typeof x === "number" ? x : NaN);
    } while (isFinite(sum) && numbers.length);

    return +sum;
}

console.log("add1", add1(1, 2, 3, 4, 5));
console.log("add1", add1(1, 2, 3, 4, 5, ""));
console.log("add1", add1(1, 2, 3, 4, 5, "0xA"));
console.log("add1", add1(1, 2, 3, 4, 5, NaN));
console.log("add1", add1(1, 2, 3, 4, 5, Infinity));
console.log("add1", add1(1, 2, 3, 4, 5, -Infinity));
console.log("add1", add1(1, 2, 3, 4, 5, true));
console.log("add1", add1(1, 2, 3, 4, 5, false));
console.log("add1", add1(1, 2, 3, 4, 5, null));
console.log("add1", add1(1, 2, 3, 4, 5, undefined));
console.log("add1", add1(1, 2, 3, 4, 5, []));
console.log("add1", add1(1, 2, 3, 4, 5, {}));

我们可以在不检查的情况下进行比较

function add2() {
    return [].reduce.call(arguments, function (a, b) {
        return a + b;
    });
}

console.log("add1", add2(1, 2, 3, 4, 5));
console.log("add1", add2(1, 2, 3, 4, 5, ""));
console.log("add2", add2(1, 2, 3, 4, 5, "0xA"));
console.log("add2", add2(1, 2, 3, 4, 5, NaN));
console.log("add2", add2(1, 2, 3, 4, 5, Infinity));
console.log("add2", add2(1, 2, 3, 4, 5, -Infinity));
console.log("add2", add2(1, 2, 3, 4, 5, true));
console.log("add2", add2(1, 2, 3, 4, 5, false));
console.log("add2", add2(1, 2, 3, 4, 5, null));
console.log("add2", add2(1, 2, 3, 4, 5, undefined));
console.log("add2", add2(1, 2, 3, 4, 5, []));
console.log("add2", add2(1, 2, 3, 4, 5, {}));

开启jsfiddle

引入的这些额外检查对性能有何影响?

让我们看看,jsperf

请随意将其他解决方案添加到性能测试中。 - 我添加了其他解决方案。

无论如何,我会避免在循环通过arguments 对象时使用for..in(以避免循环通过可能已附加到arguments 的任何方法)并且会选择任何其他常用的Array 循环方法:forwhileforEachreduce

查看相关性:Why is using “for…in” with array iteration such a bad idea?

【讨论】:

    猜你喜欢
    • 2014-04-10
    • 1970-01-01
    • 2011-07-27
    • 2012-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 2015-11-29
    相关资源
    最近更新 更多