Javascript:更新数组中嵌套对象的属性会为所有相似的对象更新相同的属性

时间:2018-11-05 08:14:30

标签: javascript jquery json

我在代码中遇到了这种奇怪的行为,我在其中更新了对象数组中嵌套对象的单个属性。奇怪的是,所有相似对象的相同属性都在更新。

代码:

let financials = {
  qr: {
    controlData: [
      {
        "year": "2013",
        "quarters": [
          {
            "month": "Mar",
            "name": "first",
            "alias": "Q1",
            "isChecked": true
          },
          {
            "month": "Jun",
            "name": "second",
            "alias": "Q2",
            "isChecked": true
          },
          {
            "month": "Sep",
            "name": "third",
            "alias": "Q3",
            "isChecked": true
          },
          {
            "month": "Dec",
            "name": "fourth",
            "alias": "Q4",
            "isChecked": true
          }
        ]
      },
      {
        "year": "2014",
        "quarters": [
          {
            "month": "Mar",
            "name": "first",
            "alias": "Q1",
            "isChecked": true
          },
          {
            "month": "Jun",
            "name": "second",
            "alias": "Q2",
            "isChecked": true
          },
          {
            "month": "Sep",
            "name": "third",
            "alias": "Q3",
            "isChecked": true
          },
          {
            "month": "Dec",
            "name": "fourth",
            "alias": "Q4",
            "isChecked": true
          }
        ]
      },
      {
        "year": "2015",
        "quarters": [
          {
            "month": "Mar",
            "name": "first",
            "alias": "Q1",
            "isChecked": true
          },
          {
            "month": "Jun",
            "name": "second",
            "alias": "Q2",
            "isChecked": true
          },
          {
            "month": "Sep",
            "name": "third",
            "alias": "Q3",
            "isChecked": true
          },
          {
            "month": "Dec",
            "name": "fourth",
            "alias": "Q4",
            "isChecked": true
          }
        ]
      }
    ]
  }
};

$('.checkbox.quarterly').click(function (e) {
    try {
        // var selectedYear = $('.dropdown.quarterly').dropdown('get value');
        // var month = $(this).find('.checkbox-input').data('month');
        // var prop = $(this).find('.checkbox-input').prop('checked');
        // var targetObj = _.findWhere(financials.qr.controlData, { year: selectedYear });

        // Values assumed
        var selectedYear = '2013';
        var month = 'Mar';
        var prop = false;
        var targetObj = _.findWhere(financials.qr.controlData, { year: selectedYear });

        $.each(targetObj.quarters, function (key, quarter) {
            if (quarter.month === month) {
                quarter.isChecked = prop;
            }
        });
    } catch (ex) {
        console.log(ex);
    }
});

实际输出:

controlData: [
  {
    "year": "2013",
    "quarters": [
      {
        "month": "Mar",
        "name": "first",
        "alias": "Q1",
        "isChecked": false
      },
      {
        "month": "Jun",
        "name": "second",
        "alias": "Q2",
        "isChecked": true
      },
      {
        "month": "Sep",
        "name": "third",
        "alias": "Q3",
        "isChecked": true
      },
      {
        "month": "Dec",
        "name": "fourth",
        "alias": "Q4",
        "isChecked": true
      }
    ]
  },
  {
    "year": "2014",
    "quarters": [
      {
        "month": "Mar",
        "name": "first",
        "alias": "Q1",
        "isChecked": false
      },
      {
        "month": "Jun",
        "name": "second",
        "alias": "Q2",
        "isChecked": true
      },
      {
        "month": "Sep",
        "name": "third",
        "alias": "Q3",
        "isChecked": true
      },
      {
        "month": "Dec",
        "name": "fourth",
        "alias": "Q4",
        "isChecked": true
      }
    ]
  },
  {
    "year": "2015",
    "quarters": [
      {
        "month": "Mar",
        "name": "first",
        "alias": "Q1",
        "isChecked": false
      },
      {
        "month": "Jun",
        "name": "second",
        "alias": "Q2",
        "isChecked": true
      },
      {
        "month": "Sep",
        "name": "third",
        "alias": "Q3",
        "isChecked": true
      },
      {
        "month": "Dec",
        "name": "fourth",
        "alias": "Q4",
        "isChecked": true
      }
    ]
  }
]

预期输出:

controlData: [
  {
    "year": "2013",
    "quarters": [
      {
        "month": "Mar",
        "name": "first",
        "alias": "Q1",
        "isChecked": false
      },
      {
        "month": "Jun",
        "name": "second",
        "alias": "Q2",
        "isChecked": true
      },
      {
        "month": "Sep",
        "name": "third",
        "alias": "Q3",
        "isChecked": true
      },
      {
        "month": "Dec",
        "name": "fourth",
        "alias": "Q4",
        "isChecked": true
      }
    ]
  },
  {
    "year": "2014",
    "quarters": [
      {
        "month": "Mar",
        "name": "first",
        "alias": "Q1",
        "isChecked": true
      },
      {
        "month": "Jun",
        "name": "second",
        "alias": "Q2",
        "isChecked": true
      },
      {
        "month": "Sep",
        "name": "third",
        "alias": "Q3",
        "isChecked": true
      },
      {
        "month": "Dec",
        "name": "fourth",
        "alias": "Q4",
        "isChecked": true
      }
    ]
  },
  {
    "year": "2015",
    "quarters": [
      {
        "month": "Mar",
        "name": "first",
        "alias": "Q1",
        "isChecked": true
      },
      {
        "month": "Jun",
        "name": "second",
        "alias": "Q2",
        "isChecked": true
      },
      {
        "month": "Sep",
        "name": "third",
        "alias": "Q3",
        "isChecked": true
      },
      {
        "month": "Dec",
        "name": "fourth",
        "alias": "Q4",
        "isChecked": true
      }
    ]
  }
]

基本上我想做的是,每当我单击相应的复选框时,都要更新特定月份的属性“ isChecked”。我的项目在带有Webpack的Laravel Mix上运行。

更新

这是创建controlData的方式:

let years = ['2013', '2014', '2015'];

let quarters = [
    {
        month: 'Mar',
        name: 'first',
        alias: 'Q1',
        isChecked: true
    },
    {
        month: 'Jun',
        name: 'second',
        alias: 'Q2',
        isChecked: true
    },
    {
        month: 'Sep',
        name: 'third',
        alias: 'Q3',
        isChecked: true
    },
    {
        month: 'Dec',
        name: 'fourth',
        alias: 'Q4',
        isChecked: true
    }
];

for(let x in years) {
    let obj = {
        year: years[x],
        quarters: quarters
    };

    financials.qr.controlData.push(obj);
}

2 个答案:

答案 0 :(得分:0)

对我来说,它看起来还不错。仅将2013年3月的值设置为false。

Underscore v1.8.3
jQuery v3.3.2

https://jsfiddle.net/7o1tx49d/4/

答案 1 :(得分:0)

您可以通过映射对象的副本来创建具有独立对象的独立数组。

financials.qr.controlData = years.map(year => ({
    year,
    quarters: quarters.map(o => Object.assign({}, o))
}));

var financials = { qr: {} },
    quarters = [{ month: 'Mar', name: 'first', alias: 'Q1', isChecked: true }, { month: 'Jun', name: 'second', alias: 'Q2', isChecked: true }, { month: 'Sep', name: 'third', alias: 'Q3', isChecked: true }, { month: 'Dec', name: 'fourth', alias: 'Q4', isChecked: true }],
    years = ['2013', '2014', '2015'];

financials.qr.controlData = years.map(year => ({
    year,
    quarters: quarters.map(o => Object.assign({}, o))
}));

var selectedYear = '2013',
    month = 'Mar',
    prop = false,
    targetObj = _.findWhere(financials.qr.controlData, { year: selectedYear });

$.each(targetObj.quarters, function (key, quarter) {
    if (quarter.month === month) {
        quarter.isChecked = prop;
    }
});

console.log(financials);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>