【问题标题】:ES6 module immutabilityES6 模块不变性
【发布时间】:2018-07-08 16:39:38
【问题描述】:

我认为 ES6 模块导出总是不可变的,所以我对我得到的行为感到很困惑。我有一个简单的颜色数组,我想在我的 Vue 应用程序的多个组件中使用它们。它在它自己的文件中,如下所示:

export const colors = [
  '#ffb3ba',
  '#ffdfba',
  '#ffffba',
  '#bae1ff',
]

然后我将它导入到我想像这样使用它的组件中:

import { colors } from '../assets/colors';

我有一个选择随机颜色的功能,然后将其从列表中删除,这样就不会为同一个组件再次选择它。是这样的。

descriptions.forEach(item => {
      const colorIndex = Math.floor(Math.random() * colors.length);
      item['color'] = colors[colorIndex];
      colors.splice(colorIndex, 1);
    });

这里的想法是从列表中选择一种随机颜色,为其分配描述,然后将其从列表中删除,以便在 forEach 的下一次迭代中选择不同的颜色。

问题是它似乎要从列表中永久删除颜色。因此,当我导入并尝试在另一个组件中使用该数组时,其中没有颜色。我怎样才能让每个组件都有一个新的 colors 数组实例?

【问题讨论】:

  • 创建一个克隆,这样你就有了你的列表,然后是一个可用列表,它会根据选定或取消选定的颜色进行更新。你在导入一个数组,可以修改里面的值,但是不能重新赋值

标签: ecmascript-6 vue.js es6-modules


【解决方案1】:

导入的绑定 是不可分配的,仅此而已。它们类似于const - 您无法更改变量but you can mutate the object it holds。为防止这种情况,请在导出对象时将其冻结:

export const colors = Object.freeze([
  '#ffb3ba',
  '#ffdfba',
  '#ffffba',
  '#bae1ff',
]);

如何才能使每个组件都有一个新的 colors 数组实例?

请查看Copying array by value in JavaScript:只需colors.slice()。此外,您还需要查看 How to randomize (shuffle) a JavaScript array?,了解如何有效地为您的描述获取随机颜色 - 甚至有 some answers 不会改变输入。

import { colors } from '../assets/colors';
import { shuffle } from '…';
const randomColors = shuffle(colors.slice());
console.assert(descriptions.length <= randomColors.length);
for (const [i, description] of descriptions.entries())
  description.color = randomColors[i];

【讨论】:

  • 谢谢,但我不明白你的解决方案。当我使用Object.freeze 时,我收到错误:TypeError: Cannot add/remove sealed array elements。我的随机化方法有什么问题?您链接的那些要复杂得多。
  • 是的,冻结只是防止删除工作的安全措施。您仍然需要使用.slice()(或Array.from 或其他)制作实际副本。
  • 您的随机化方法确实效率低下,反复从数组中间删除东西具有O(n²) 复杂性。只需使用标准的 Fisher-Yates 洗牌(它并不那么复杂)...
  • 只有 5 个项目真的很重要吗?我无法确定费舍尔-耶茨洗牌的正面或反面。 var currentIndex = array.length, temporaryValue, randomIndex;我从未见过这样分配的变量。逗号分隔是什么意思?
  • @MattGween 这只是declaring multiple variables。您可能会发现来自another answer 的代码更具可读性……
【解决方案2】:

正如您正确观察到的那样,ES6 模块导入不是不可变的。


您可以创建数组的浅表副本并对其进行操作:

const copiedColors = [...colors];

descriptions.forEach(item => {
  const colorIndex = Math.floor(Math.random() * colors.length);
  item['color'] = copiedColors[colorIndex];
  copiedColors.splice(colorIndex, 1);
});

【讨论】:

    猜你喜欢
    • 2018-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-05
    • 2014-10-09
    • 2017-01-04
    相关资源
    最近更新 更多