如何在ES6中将结构化为动态命名的变量?

Ana*_*ass 43 javascript ecmascript-6

我们假设我有以下对象:

const user = { 
  id: 42, 
  displayName: "jdoe",
  fullName: { 
      firstName: "John",
      lastName: "Doe"
  }
};
Run Code Online (Sandbox Code Playgroud)

而我只想要idfullName.

我会做以下事情:

const { id, fullName } = user
Run Code Online (Sandbox Code Playgroud)

轻松,对吧?

现在让我们假设我想根据另一个变量的值来进行解构fields.

const fields = [ 'id', 'fullName' ]
Run Code Online (Sandbox Code Playgroud)

现在我的问题是:我如何根据一系列密钥进行解构?

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

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

谢谢

Pau*_*gel 28

使用动态密钥进行结构化并非不可能.为了防止创建动态变量的问题(如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" }
Run Code Online (Sandbox Code Playgroud)

要解决必须为动态值定义静态别名的问题,可以分配给对象的动态属性.在这个简单的例子中,这与恢复整个解构相同,但:)

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" }
Run Code Online (Sandbox Code Playgroud)

来源:

  • 不幸的是,您提出的解决方案都没有回答问题. (4认同)

Muh*_*nar 11

如前所述,不使用 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);
Run Code Online (Sandbox Code Playgroud)

  • 与感谢一起使用的变体:https://github.com/davelopware/example-ts-mongo-express (3认同)

jun*_*var 8

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

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

let {[dynamicField]: value} = obj;

console.log(value);
Run Code Online (Sandbox Code Playgroud)


Gin*_*den 6

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

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

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

  • 您提出的作用域范围无懈可击。但是,至少有一种情况本身不是代码气味。即,当您具有接受要在迭代中使用的一个或多个键的函数时。特殊版本的omit,pluck和reduce都是动态解构有助于提高可读性的情况。在对象中动态分配字段名称既是可行的,也是启用DRYer代码(即更多代码共享)的绝佳方法。以同样的方式,动态分配指针可以帮助DRY代码,而无需使用哈希图来规避语言限制。 (2认同)

Fra*_*ion 5

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

// 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; 
Run Code Online (Sandbox Code Playgroud)

解决方案是使用Array.reduce()动态键创建一个对象,如下所示:

// 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; 
Run Code Online (Sandbox Code Playgroud)