如何在ES2015中解构所有属性到当前作用域/闭包

How do I destructure all properties into the current scope/closure in ES2015?

本文关键字:属性 作用域 闭包 ES2015      更新时间:2023-09-26

我想这样做:

const vegetableColors = {corn: 'yellow', peas: 'green'};
const {*} = vegetableColors;
console.log(corn);// yellow
console.log(peas);// green

我似乎找不到或弄不清楚如何做到这一点,但我真的以为我以前在什么地方见过这样做!: P

注意:我使用Babel与stage设置为0;

CONTEXT:我试图在JSX中更干燥,而不是到处引用this.statethis.props。而且,如果数据发生变化,也不必不断添加属性来解构。

我想你正在寻找with语句,它完全符合你的要求:

const vegetableColors = {corn: 'yellow', peas: 'green'};
with (vegetableColors) {
    console.log(corn);// yellow
    console.log(peas);// green
}

然而,它是不赞成(在严格模式下,包括ES6模块),有很好的理由。

将所有属性解构到当前作用域

在ES61中不能。这是一件好事。明确你要引入的变量:

const {corn, peas} = vegetableColors;

或者,您可以使用Object.assign(global, vegetableColors)扩展全局对象,将它们置于全局作用域中,但实际上,这比with语句更糟糕。

1:…虽然我不知道是否有一个草案允许在ES7中这样做,但我可以告诉你,任何提议都会被TC否决:-)

我不推荐这样做,但是您可以使用eval()来完成类似的事情:

vegetableColors = {corn: 'yellow', peas: 'green'};
function test() {
    for ( let i=0; i < Object.keys(vegetableColors).length; i++ ) {
        let k = Object.keys(vegetableColors)[i];
        eval(`var ${k} = vegetableColors['${k}']`);
    }
    console.log(corn); // yellow
}
test();
console.log(corn); // undefined (out of scope)

我想你要找的是:

const {corn, peas} = vegetableColors;

Live on Babel's REPL


如果Pointy是对的,你问如何在不知道cornpeas名字的情况下完成,那么你就不能用解构赋值。

你只能在全局作用域中使用循环,但我确信你不想在全局作用域中这样做。不过,以防万一:

// I'm sure you don't really want this, just being thorough
Object.keys(vegetableColors).forEach((key) => {
    Object.defineProperty(this, key, {
        value: vegetableColors[key]
    });
});

(如果你想让这些伪常量是可枚举的,就在那里设置enumerable: true)

在全局作用域中工作,因为this引用全局对象。

我遇到了这样一种情况:对象是用户创建的,使用该对象的代码也是用户创建的。因为with语句已被弃用,所以我创建了自己的语句,使用eval解构整个对象并调用使用解构对象的函数。下面是一个工作示例:

const vegetableColors = { corn: 'yellow', peas: 'green' };
function with2(obj, func) {
  eval(`
    var { ${Object.keys(obj).join(",")} } = obj;
    (${func.toString()})()
  `);
}
/*
with(vegetableColors) {
  console.log(corn);
  console.log(peas);
}
*/
with2(vegetableColors, function() {
  console.log(corn);
  console.log(peas);
})

让我告诉你我解决这个问题的方法。我不同意那些认为在局部范围内解构对象属性而不指定其名称是坏主意的人。对我来说,这个功能如果实现了,将会很有帮助。这将使我们的代码更短,并通过在不更改处理代码的情况下轻松更改属性名称来改进代码维护。毕竟,PHP中有extract()函数可以做同样的事情。PHP开发人员错了吗?

我的解决方案是不理想的,因为它使用eval,但它是一个行,它的工作。也许在未来,我们会从JavaScript开发者那里得到一个解决方案。

function extract(o)
{
  var result = [];
  
  for(var key in o)
    if(o.hasOwnProperty(key)) {
      var item = 'var ' + key + '=' + JSON.stringify(o[key]); 
      result.push(item);
    }
  
  return result.join(';');
}
var vegetableColors = { corn: 'yellow', peas: { unripe: 'green', ripe: 'yellow' } };
eval(extract(vegetableColors));
console.log(corn);  // yellow
console.log(peas);  // {unripe: "green", ripe: "yellow"}