我正在使用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;
更新:阅读浅谈&amp;深度复制我想在此处记录另一种解决方案是使用jQuery中的$ .extend方法在JavaScript对象中执行深层复制。 e.g。
$.extend(true, {} , xOptions, yOptions);
答案 0 :(得分:3)
您遗漏的一点是Object.assign
执行了所提供对象属性的浅副本。
xOptions
和yOptions
都是具有单个属性的对象: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