【问题标题】:How to use destructuring assignment to define enumerations in ES6?如何使用解构赋值来定义 ES6 中的枚举?
【发布时间】:2017-02-02 01:45:06
【问题描述】:

您可以使用解构赋值来定义 ES6 中的枚举,如下所示:

var [red, green, blue] = [0, 1, 2];

相反,我希望解构赋值的右侧是动态的。例如:

var MAX_ENUM_SIZE = 32;
var ENUM = new Array(MAX_ENUM_SIZE);
for (var i = 0; i < MAX_ENUM_SIZE; i++) ENUM[i] = i;

var [red, green, blue] = ENUM;

不幸的是,这似乎是一个 hack。如果我将来想要更大的枚举怎么办?因此,我正在考虑使用带有迭代器的解构赋值,如下所示:

var [red, green, blue] = enumeration(/* I don't want to specify size */);

但是,我认为不可能将解构赋值与迭代器一起使用[需要引用]。有没有办法实现这个目标?

【问题讨论】:

  • 为什么这是个好主意?
  • 你只需要前三个值和三个目标变量,
  • 不那么脆弱的代码?如果有人为枚举添加了一个新的替代项并且忘记更新右侧,那么您可能会收到错误消息。但是,如果右侧是动态的,则不必担心。
  • 您是否尝试动态创建变量名称以对应enumeration 返回的未知数量的元素?
  • @AaditMShah 您希望枚举与 L​​HS 上指定的 var 名称的数量相匹配吗?

标签: javascript enums iterator ecmascript-6 destructuring


【解决方案1】:

使用生成器

function* enumerator() {
  let i = 0;
  while (true) yield i++;
};

let [red,green,blue] = enumerator();
console.log(red, green, blue); // 0 1 2

let [a,b,c,d,e] = enumerator();
console.log(a,b,c,d,e); // 0 1 2 3 4

生成器非常灵活,可以很好地实现不同类型的枚举——例如,这些可爱的位掩码枚举

function* bitmask() {
  let i = 0;
  while (i < 32) yield 1 << i++;
  throw Error("bitmask enumerator exceeds 32 bits");
}

let [R,W,X] = bitmask();

const read = p => (p & R) !== 0;
const write = p => (p & W) !== 0;
const exec = p => (p & X) !== 0;

{
  let p = R | W; // read and write only
  console.log("can read?", read(p));   // true
  console.log("can write?", write(p)); // true
  console.log("can exec?", exec(p));   // false
}

{
  let p = R | X; // read and execute only
  console.log("can read?", read(p));    // true
  console.log("can write?", write(p));  // false
  console.log("can exec?", exec(p));    // true
}

【讨论】:

  • 说实话,在尝试这个之前我不知道可以解构生成器。很酷的把戏——当然,当负责任地使用时。我认为您的枚举器案例非常适合此。
  • 位掩码生成器应该从0循环到30(或最多31)然后抛出异常。
  • 来自 Python,在 Python 中,生成器需要与变量数量一样多的项目,阅读这样的代码会感觉有点奇怪。
  • @Bergi 谢谢——它是作为一个幼稚的实现提出的,但最好是彻底的^_^
  • 零计算为假值。您可能希望以 i=1 开始枚举。
【解决方案2】:

请注意,以下每种可能的方法都可能会得到改进。

变量在 Question 中似乎是全局的。您可以创建一个引用应该创建的变量的字符串数组,从数组元素定义变量

// not technically destructuring, though achieves same result;
// that is, setting variables globally
for (var prop of (props = ["a", "b", "c", "d"])) {
  // set identifier globally
  self[prop] = props.indexOf(prop); // set a value for each `prop`
}
// delete `prop`, `props`
prop = props = void 0;

console.log(a, b, c, d);

其他方法

使用对象解构

var {
  red, blue, green
} = (function(data, props) {
      for (var prop of Object.keys(props)) {
        data[props[prop]] = props.indexOf(props[prop]); // or some other value
      };
      return data
    }({}, ["red", "blue", "green"]));

console.log(red, blue, green);

使用变量列表

var props = ["red", "blue", "green"]; // list of variables to be
var [red, blue, green] = props.map((v, k) => k);
console.log(red, blue, green, "window[\"red\"]:", window[props[0]]);

【讨论】:

  • 感谢您在此答案中付出的努力,但我认为您误解了我的问题。无论如何,我赞成你的回答。 =)
  • 注意Array.from 接受第二个参数,它是一个映射函数——除此之外,我不确定这个答案是“解决”什么
  • @naomik 调整方法以使用 Array.from() 而不传递变量
  • @AaditMShah 如果与问题不符,为什么要投票?它应该是评论,而不是答案。
  • OP 要求提供不涉及指定(最大)大小的解决方案。您的回答未能提供这一点。
猜你喜欢
  • 1970-01-01
  • 2018-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
  • 2018-03-16
  • 1970-01-01
  • 2012-08-31
相关资源
最近更新 更多