JavaScript中reduce函数中的三元运算符返回

3

我有一个这样的数据结构:

var example = [
    { name: "item1", year: 2013, value: 100 },
    { name: "item1", year: 2012, value:  97 },
    { name: "item3", year: 2013, value:  93 },
    { name: "item3", year: 2012, value:  91 },
    { name: "item2", year: 2012, value:  -6 },
    { name: "item2", year: 2011, value:  -5 },
    { name: "item4", year: 2012, value: -36 },
    { name: "item3", year: 2011, value:  93 },
    { name: "item4", year: 2013, value: -35 },
    { name: "item1", year: 2011, value:  98 },
    { name: "item2", year: 2013, value:  -7 },
    { name: "item4", year: 2011, value: -37 },
    { name: "item5", year: 2013, value:  58 },
    { name: "item5", year: 2012, value:  55 },
    { name: "item5", year: 2011, value:  54 }
];

我正在使用这个函数来获取单一元素的数组:
example.reduce(function (prev, curr) {
    if (prev.indexOf(curr.name) === -1) prev.push(curr.name);
    return prev;
}, []);

虽然这样可以运行,但为了可读性,我尝试使用三元运算符进行改写,如下所示:
example.reduce(function (prev, curr) {
    return prev.indexOf(curr.name) === -1 ? prev.push(curr.name) : prev;
}, []);

在 Chrome 中,我收到以下错误:

Uncaught TypeError: prev.indexOf is not a function
    at <anonymous>:3:13
    at Array.reduce (native)
    at <anonymous>:2:9
    at Object.InjectedScript._evaluateOn (<anonymous>:895:140)
    at Object.InjectedScript._evaluateAndWrap (<anonymous>:828:34)
    at Object.InjectedScript.evaluate (<anonymous>:694:21)

为什么会这样?

这是因为push函数不会返回相同的数组。 - Mritunjay
2
这是因为 .push 不会返回一个数组,而是返回新数组的长度。 - Aadit M Shah
2个回答

5
这是因为调用.push()方法会返回一个数字类型的数组长度,所以第二次调用prev时将会得到一个没有push方法的数字(1)。因此在这种情况下,使用 if 条件语句会更好。
引用Mozilla Developer Network中的说明:方法被调用后,返回该对象的新长度属性。
如果您仍想使用三目运算符,可以使用hacky解决方案:
var b = example.reduce(function (prev, curr) {
    return prev.indexOf(curr['name']) === -1 ? prev.push(curr['name']) && prev : prev;
}, []);

你可以让你的解决方案更加专业。请参考我上面的回答。 - Aadit M Shah

2

将三元运算符替换为&&,,而不是?:,如下所示:

example.reduce(function (prev, curr) {
    return prev.indexOf(curr.name) < 0 && prev.push(curr.name), prev;
}, []);

在这种情况下,我们使用逻辑 AND 来测试是否 prev.indexOf(curr.name) < 0,如果是,则执行 prev.push(curr.name)。然而,由于 逗号操作符,我们总是返回 prev

正如我在评论中提到的那样,您的代码无法工作,因为.push 不会返回原始的数组,而是返回数组的新长度。您可以用.concat 替换 .push,但效率会很低。上述方法更好。


谢谢,虽然你的回答是正确的,我也学到了更多关于逗号运算符的知识,但为了可读性,我更喜欢使用三元运算符。我会尝试做一个 jsperf 来看哪个更高效,并根据情况进行选择。 - Bondifrench

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接