如何在 ES6 中解构为动态命名的变量?

IT技术 javascript ecmascript-6
2021-01-18 23:57:55

假设我有以下对象:

const user = { 
  id: 42, 
  displayName: "jdoe",
  fullName: { 
      firstName: "John",
      lastName: "Doe"
  }
};

而且我只想要idfullName

我将执行以下操作:

const { id, fullName } = user

容易,对吧?

现在让我们假设我想根据另一个名为fields.

const fields = [ 'id', 'fullName' ]

现在我的问题是:如何根据键数组进行解构?

我无耻地尝试了以下但没有成功:

let {[{...fields}]} = userlet {[...fields]} = user有什么办法可以做到这一点吗?

谢谢

5个回答

使用动态密钥进行解构并非不可能。为了防止创建动态变量的问题(如 Ginden 提到的),您需要提供别名。

const user = { 
  id: 42, 
  displayName: "jdoe",
  fullName: { 
      firstName: "John",
      lastName: "Doe"
  }
};

const fields = [ 'id', 'fullName' ];
const object = {};

const {[fields[0]]: id, [fields[1]]: fullName} = user;

console.log(id); // 42
console.log(fullName); // { firstName: "John", lastName: "Doe" }

要解决必须为动态值定义静态别名的问题,您可以分配给对象的动态属性。在这个简单的例子中,这与恢复整个解构是一样的,虽然:)

const user = { 
  id: 42, 
  displayName: "jdoe",
  fullName: { 
      firstName: "John",
      lastName: "Doe"
  }
};

const fields = [ 'id', 'fullName' ];
const object = {};

({[fields[0]]: object[fields[0]], [fields[1]]: object[fields[1]]} = user);

console.log(object.id); // 42
console.log(object.fullName); // { firstName: "John", lastName: "Doe" }

来源:

不幸的是,您提出的解决方案都没有回答所提出的问题。
2021-04-01 23:57:55

简短的回答:这是不可能的,也不可能。

这背后的原因是:它会将新的动态命名变量引入块范围,实际上是动态的eval,从而禁用任何性能优化。eval可以在 fly 中修改范围的动态一直被认为是极其危险的,并从 ES5 严格模式中删除。

此外,这将是一种代码异味 - 引用未定义的变量 throws ReferenceError,因此您需要更多样板代码来安全地处理此类动态范围。

那确实是一种代码异味。最终使用了另一种方法。
2021-03-12 23:57:55
你提出的范围点是无懈可击的。但是,至少在一种情况下,它本身不是代码异味。即,当您有一个函数接受一个或多个要在迭代中使用的键时。omit, pluck& 的特殊版本reduce都是动态解构有助于提高可读性的所有情况。对象中字段名称的动态分配既是可能的,也是启用 DRYer 代码(即更多代码共享)的绝佳方式。同样,指针的动态分配可以帮助 DRY 代码,而无需使用哈希映射来规避语言限制。
2021-03-23 23:57:55

如前所述,不使用 eval 就无法在 JavaScript 中分解为动态命名的变量。

但是你可以使用reduce函数动态获取对象的一个​​子集,如下所示:

const destruct = (obj, ...keys) => 
  keys.reduce((a, c) => ({ ...a, [c]: obj[c] }), {});

const object = { 
  color: 'red',
  size: 'big',
  amount: 10,
};

const subset1 = destruct(object, 'color');
const subset2 = destruct(object, 'color', 'amount', 'size');
console.log(subset1);
console.log(subset2);

2021-03-12 23:57:55

Paul Kögel 的回答很好,但我想举一个更简单的例子,说明当您只需要动态字段的值但不需要将其分配给动态键时。

let obj = {x: 3, y: 6};
let dynamicField = 'x';

let {[dynamicField]: value} = obj;

console.log(value);

如果不知道键的名称或对命名变量使用别名,则无法进行破坏

// you know the name of the keys
const { id, fullName } = user;

// use an alias for named variables
const { [fields[0]]: id, [fields[1]]: fullName } = user; 

一个解决方案是使用Array.reduce()这样的动态键来创建一个对象:

const user = { 
  id: 42, 
  displayName: "jdoe",
  fullName: { 
      firstName: "John",
      lastName: "Doe"
  }
};

const fields = [ 'id', 'fullName', 'age' ];

const obj = fields.reduce((acc, k) => ({ ...acc, ...(user.hasOwnProperty(k) && { [k]: user[k] }) }), {});

for(let k in obj) {
  console.log(k, obj[k]);
}