JS - 将键添加到一个变量会将其添加到链式赋值中创建的所有变量

JS - Adding key to one variable adds it to all the variables created in chained assignment

我创建了一个对象并将其分配给 3 个变量,就像这样

var barChartOptions, longChartOptions, scatterOptions;
barChartOptions = longChartOptions = scatterOptions = {
    legend: {
        display: false
    },
    scales: {
        ...
    }
};

也试过

var barChartOption = longChartOptions = scatterOptions = {
    legend: {
        display: false
    },
    scales: {
        ...
    }
};

然后我尝试向其中一个变量添加一个键。此键仅特定于此一个变量,对象的其余部分对于所有变量都是相同的。

longChartOptions.aspectRatio = 3;

现在,所有三个变量都有键 aspectRatio。为什么会这样?我知道如果我分别定义这三个变量,问题就不会发生,但是对象很长,我想让代码保持干燥。

创建一个 returns 对象的函数,并在定义每个变量时调用该函数:

const makeOptions = () => ({
  legend: {
    display: false
  },
  scales: {
    // ...
  }
});
const barChartOptions = makeOptions(),
      longChartOptions = makeOptions(),
      scatterOptions = makeOptions();

Why is this happening?

因为赋值解析为赋值。您的原始代码:

barChartOptions = longChartOptions = scatterOptions = { /* ... */ };

相当于:

scatterOptions = { /* ... */ };
longChartOptions = scatterOptions; // references same object
barChartOptions = longChartOptions; // references same object
// so in the end, scatterOptions === barChartOptions

每个变量名都引用内存中的同一个对象。当您将同一对象分配给不同的变量名称时,不会发生结构克隆。

您可以使用扩展运算符将对象复制到另一个变量。

var barChartOption = {...longChartOptions} = {...scatterOptions} = {
    legend: {
        display: false
    },
    scales: {
      // ...
    }
};

实际上,当您使用 = 号将对象复制到变量时 javascript 将对象的引用复制到该变量。因此,当您更改任何变量上的任何内容时,它也会反映另一个变量。

要摆脱这种情况,您可以使用扩展运算符或@CertainPerformance 提到的过程。

问题是所有变量都指向同一个内存块。您可以使用 es6 传播运算符来创建不同的实例。

var barChartOptions, longChartOptions, scatterOptions;
{...barChartOptions} = {...longChartOptions} = {...scatterOptions} = {
    legend: {
        display: false
    },
    scales: {
        ...
    }
};