在Babel中使用赋值进行Javascript对象解构

时间:2016-12-24 03:22:34

标签: webpack ecmascript-6 babeljs

我有以下对象:

const action = {id: 100, name: 'Andres', age: 27, type: 'CREATE_USER'}

我想将一些属性复制到另一个对象中。在最新版本的Chrome中,我可以这样做:

const newUser = {id, name, age} = action;

newUser对象包含:

{id: 100, name: 'Andres', age: 27}

这在浏览器中运行良好。但是,使用我编译的JS代码它并不起作用。我明白了:

 error ReferenceError: id is not defined

如果我删除id,我会使用不同的密钥获得相同的消息,依此类推。

我的设置:

"webpack": "2.1.0-beta.21"
"webpack-dev-server": "2.1.0-beta.0"

对于巴别塔:

"babel-core": "6.x",
"babel-eslint": "6.x",
"babel-loader": "6.x",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-runtime": "6.x",
"babel-polyfill": "^6.8.0",
"babel-preset-es2015": "6.x",
"babel-preset-es2015-native-modules": "^6.6.0",
"babel-preset-react": "6.x",
"babel-preset-stage-0": "6.x",

Babel或Webpack是否缺少我想要的东西来完成我想要的东西?

2 个答案:

答案 0 :(得分:6)

这里的问题是你一次尝试声明并分配给变量,而在严格模式语义下这是不允许的,这是由Babel强制执行的。因此,您的代码段比您预期的更多:

 const newUser = {id, name, age} = action;

作为evaluating the destructuring expression的一部分,将对idnameage,不存在的引用执行分配,这些引用应该引发ReferenceError根据{{​​3}}的异常。更具体地说,底部有一个说明:

  

当在严格模式代码中发生赋值时,如果在第一个算法的步骤1.f中的 lref 或第二个算法的步骤7中它是一个运行时错误,则它是一个不可解析的引用。如果是,则抛出 ReferenceError 异常。

您可以尝试在控制台中运行此代码段来证明:



// Will work
(function () {
  a = 5;
})();

// Won't work
(function () {
  'use strict';
  b = 5;
})()




为了让Babel以我认为你想要的方式工作,你必须放弃ES2015预设并手动包含所有插件,选择退出the specification。简而言之,您将自己打开一罐PITA。

正确的做法是声明您要绑定到的属性的所有变量:



'use strict';

let a, b, c;

({fee: a, fii: b, foo: c} = {fee: 1, fii: 2, foo: 3});
console.log(a, b, c);




不幸的是,这仍然无法满足您的需求。解构表达式的结果是一个赋值表达式,其中返回的值将是赋值(析构)的值,因此您的newUser实际上不会像预期的那样成为新对象:



const action = {id: 100, name: 'Andres', age: 27, type: 'CREATE_USER'}
const newUser = {id, name, age} = action;

console.log(newUser === action);




这使我们得到以下解决方案。它可能不那么简洁,但它清楚地概述了正在进行的工作:



const action = {id: 100, name: 'Andres', age: 27, type: 'CREATE_USER'}
const {id, name, age} = action;

const newUser = {id, name, age};




答案 1 :(得分:1)

const action = {id: 100, name: 'Andres', age: 27, type: 'CREATE_USER'}    
const newUser = {id, name, age} = action;
  

newUser对象包含:

{id: 100, name: 'Andres', age: 27}

不,它没有。它仍包含type属性。原因是第二个语句被解析为:

const newUser = ({id, name, age} = action);

换句话说,newUser被分配给评估作业声明的结果 ({id, name, age}) = action。赋值语句的计算结果为其右侧。在这种情况下,它因此评估为action。总的来说,您的赋值语句完全等同于以下两个赋值:

({id, name, age} = action);
const newUser = action;

这几乎肯定不是你想要的。 id等将被隐式声明为全局变量,或者更可能导致ReferenceErrornewUser将与action相同。

您要做的是解构为另一个对象,而不是变量。 ES6中没有这样的功能。已经有一些讨论和建议,例如“选择”功能,但TC39上的权力似乎是决定性的不感兴趣。暂时,写下

const {id, name, age} = action;
const newUser = {id, name, age};

如果您可以访问传播属性功能,并且知道除了 type之外的所有,那么您可以写:

const {type, ...newUser} = actions;

但这对于“挑选”来说并不是一个很好的通用解决方案。