JavaScript .reduce()方法无法正常工作

时间:2019-06-22 18:17:34

标签: javascript jquery

我有一个对话框窗口,其中包含一个div内的各种表单元素。我想从div中包含的所有表单元素创建JSON字符串。

为此,我使用以下语句

$("#dialogServiceItems").find("select, textarea, input").serializeArray();

这很好用,但是我得到的结果是

[{"name":"FrequentExtraItemID","value":"12"},{"name":"ServiceType","value":"Testing the service type"},{"name":"Vendor","value":"Some vendor"},{"name":"Cost","value":"100"},{"name":"Description","value":"A description"},{"name":"ExtraServiceID","value":"0"},{"name":"JobExtraID","value":"79"}]

我想结束

{"FrequentExtraItemID":"12","ServiceType":"Testing the service type","Vendor":"Some vendor","Cost":"100","Description":"A description","ExtraServiceID":"0","JobExtraID":"79"}

因此,我正在使用JavaScript reduce()方法,如下所示:

var beforeReduce = $("#dialogServiceItems").find("select, textarea, input").serializeArray();
var afterReduce = beforeReduce.reduce(function (accumulator, currentValue, currentIndex) {
        if (currentIndex === 1) {
          var json = {};
          json[accumulator.name] = accumulator.value;
          return json;
        }
        accumulator[currentValue.name] = currentValue.value;
        return accumulator;
      });

但是,结果是跳过了第二个元素(ServiceType)

{"FrequentExtraItemID":"12","Vendor":"Some vendor","Cost":"100","Description":"A description","ExtraServiceID":"0","JobExtraID":"79"}

我不确定为什么要跳过第二个元素。

我创建了一个小提琴示例以在此处说明问题:https://jsfiddle.net/x4r1neah/2/

3 个答案:

答案 0 :(得分:1)

return json会在该循环迭代中吹走累加器的所有结果。

完全删除您的if语句。您还缺少要减少的初始累加器值,因此添加

beforeReduce.reduce(function() {...}, {});

要清理整个过程并避免发生变异(变异可能是不好的)和变异函数参数(大部分时间是不好的),您可以使用一些不错的新ES6速记并简单地做到:

beforeReduce.reduce((acc, {name, value}) => ({ ...acc, [name]: value }), {})

答案 1 :(得分:1)

与其在reduce循环中测试索引,不如将初始值作为第二个参数传递。一切都将更加容易阅读和理解:

let l = [{"name":"FrequentExtraItemID","value":"12"},{"name":"ServiceType","value":"Testing the service type"},{"name":"Vendor","value":"Some vendor"},{"name":"Cost","value":"100"},{"name":"Description","value":"A description"},{"name":"ExtraServiceID","value":"0"},{"name":"JobExtraID","value":"79"}]

let reduced = l.reduce((acc, {name, value}) => {
    acc[name] = value
    return acc
}, {}) // <-- pass in empty object for initial accumulator 

console.log(reduced)

答案 2 :(得分:1)

  

但是,结果是跳过了第二个元素(ServiceType)

之所以会这样,是因为如果没有initialValue

  

用作回调的第一次调用的第一个参数的值。如果未提供initialValue,则将使用数组中的第一个元素。在没有initialValue的空数组上调用reduce()会引发TypeError。

您第一次进入循环:

  • 累加器是第一个元素
  • currentValue 是第二个元素

为了丢失数据,您可以简单地通过分配更改回报:

getItems