使用Object.assign合并对象

时间:2018-01-26 15:36:28

标签: javascript object chart.js

我正在使用chart.js创建一个用户可以填写并绘制图表的表单。用户可以填写x& y在一个点标记w / font-size。我将输入作为对象保存到变量中,然后将xOptions和yOptions对象合并到chartOptions对象中,然后我可以将其分配给chart.js选项对象。问题是当我使用Object.assign而不是合并它时用第二个覆盖第一个对象???我已经在MDN上阅读了文档,我无法看到我的错误。任何指导非常感谢。有关详细信息,请参阅代码段。



$("#form").on("submit", function(e) {

  e.preventDefault();

  let chartOptions = {};
  let xOptions = {};
  let yOptions = {};
  // First grab form data off the page
  const formData = $('form').serializeArray();


  formData.forEach(function(value, index) {
    if (formData[index].name.includes('Axis')) {
      // We have an Axis label or font size form value we need 
      // to put in the chartOptions object
      switch (formData[index].name) {
        case 'xAxisLabel':
          xOptions = {
            scales: {
              xAxes: [{
                scaleLabel: {
                  display: true,
                  labelString: formData[index].value,
                  fontSize: formData[index + 1].value
                }
              }]
            }
          };

          break;
        case 'yAxisLabel':
          yOptions = {
            scales: {
              yAxes: [{
                scaleLabel: {
                  display: true,
                  labelString: formData[index].value,
                  fontSize: formData[index + 1].value
                }
              }]
            }
          };
          break;
        case 'xAxisFont':
          // do nothing
          break;
        case 'yAxisFont':
          // do nothing
          break;
      }

    }

  })

  chartOptions = Object.assign(chartOptions, xOptions, yOptions);
  console.log(xOptions);
  console.log(yOptions);
  console.log(chartOptions);

})

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />

<form id="form" role="form">
  <div class="row">
    <div class="col-xs-8">
      <div class="form-group ">
        <label for="x_axis_label">Label for X-axis</label>
        <input type="text" name="xAxisLabel" class="form-control input-lg" id="x_axis_label" placeholder="X-axis label">
      </div>
    </div>

    <div class="col-xs-4">
      <div class="form-group">
        <label for="fontsize_x">Font Size</label>
        <input type="text" name="xAxisFont" class="form-control input-lg" id="fontsize_x" placeholder="i.e. 16">
      </div>
    </div>

  </div>

  <div class="row">
    <div class="col-xs-8">
      <div class="form-group">
        <label for="y_axis_label">Label for Y-axis</label>
        <input type="text" name="yAxisLabel" class="form-control input-lg" id="y_axis_label" placeholder="Y-axis Label">
      </div>
    </div>

    <div class="col-xs-4">
      <div class="form-group">
        <label for="fontsize_y">Font Size</label>
        <input type="text" name="yAxisFont" class="form-control input-lg" id="fontsize_y" placeholder="i.e. 16">
      </div>
    </div>

  </div>
  <div class="row">
    <div class="col-md-4 col-md-offset-5">
      <button type="submit" class="btn btn-primary btn-lg" id="render_btn">
                            <span class="glyphicon glyphicon-stats" aria-hidden="true"></span>
                            Render Graph
                        </button>
    </div>
  </div>
</form>
&#13;
&#13;
&#13;

更新:阅读浅谈&amp;深度复制我想在此处记录另一种解决方案是使用jQuery中的$ .extend方法在JavaScript对象中执行深层复制。 e.g。

$.extend(true, {} , xOptions, yOptions);

2 个答案:

答案 0 :(得分:3)

您遗漏的一点是Object.assign执行了所提供对象属性的副本。

xOptionsyOptions都是具有单个属性的对象:scales,因此yOptions上的对象(位于参数列表中的xOptions之后)赢了。

MDN文档中的相关行在此处:

  

如果目标对象中的属性具有相同的键,则它们将被源中的属性覆盖。 后来的属性同样会覆盖之前的属性。

要解决此问题,您需要深度合并(这不像使用Object.assign那么简单),或者,如果您只关心scales属性,则可以合并而不是对象本身。

chartOptions.scales = Object.assign(
    {}, 
    chartOptions.scales,
    xOptions.scales, 
    yOptions.scales
);

答案 1 :(得分:1)

AFAIK,Javascript无法自动执行此操作。相反,您可以创建一个新对象并包含原始对象的属性。当重复某些属性时,会出现问题,合并对象中的值应该是多少?它取决于应用程序逻辑(两者的总和,最大值等)。

方法是:

let result = {};
let keys = new Set(Object.keys(obj1))
Object.keys(obj2).map(x => keys = keys.add(x))

keys.forEach(x => {
    result[x] = (obj1[x] || 0) + (obj2[x] || 0);
})

您可以查看此主题中的类似问题:JavaScript/Coffeescript sum objects