Javascript ES6 Destructuring - 标识符'location'已经被声明

时间:2017-01-12 13:57:44

标签: javascript ecmascript-6

我有一个简单的对象数组,想要获取第一个元素的location属性:

const companies = [
  { name: 'Google', location: 'Mountain View' },
  { name: 'Facebook', location: 'Menlo Park' },
  { name: 'Uber', location: 'San Francisco' }
];

const [{ location }] = companies; 
// expected: Mountain View but got Uncaught SyntaxError: Identifier 
//'location' has already been declared at <anonymous>:1:1

我错过了什么?

4 个答案:

答案 0 :(得分:11)

您无法将全局变量location重新定义为常量。如果您使用let [{location}] = companies,则不会出现错误,但是您会遇到错误的行为,因为它会尝试将值分配给window.location并重定向页面。

可能的解决方案:

  • 更改变量名称(以及属性名称)
  • 将代码包装在一个块中(在这种情况下不需要IIFE,因为我们使用的是ES6)
  • 您可以保留属性名称并更改变量名称,请参阅最后一个示例

const companies = [
  {name: 'Google',loc: 'Mountain View'},
  {name: 'Facebook', loc: 'Menlo Park'},
  {name: 'Uber', loc: 'San Francisco'}
];

const [{loc}] = companies;
console.log(loc);

// Block scope
{
  const companies = [
    {name: 'Google', location: 'Mountain View'},
    {name: 'Facebook', location: 'Menlo Park'},
    {name: 'Uber', location: 'San Francisco'}
  ];
  const [{location}] = companies;
  console.log(location);
}

// Variable name doesn't have to be the same as property
const [{ location: loca }] = [{location: 'Mountain View'}]
console.log(loca);

答案 1 :(得分:5)

这里的问题是您没有将代码包装在函数中。

如果使用IIFE(立即调用的函数表达式),相同的代码将起作用。

您的代码失败的原因是因为如果已经采用常量/变量名称,则无法在同一范围内声明常量。

您可以使用var代替const,但这已经分配给window.location,有效地重新加载页面并将您转到404页面,因为该网址没有存在。

这就是为什么你应该总是在IIFE中编写你的代码,以防止全局命名空间污染和难以修复的令人讨厌的错误。

这里的代码与IIFE相同(添加严格模式):

&#13;
&#13;
(() => { // ES2015 IIFE
    "use strict";
    
    const companies = [
      { name: 'Google', location: 'Mountain View' },
      { name: 'Facebook', location: 'Menlo Park' },
      { name: 'Uber', location: 'San Francisco' }
    ];
    
    const [{ location }] = companies;
    console.log(location);
})();
&#13;
&#13;
&#13;

或者更好:

&#13;
&#13;
{ // ES2015 block
    "use strict";
    
    const companies = [
      { name: 'Google', location: 'Mountain View' },
      { name: 'Facebook', location: 'Menlo Park' },
      { name: 'Uber', location: 'San Francisco' }
    ];
    
    const [{ location }] = companies; 
    console.log(location);
};
&#13;
&#13;
&#13;

鉴于您仅使用letconst(并且未使用var),使用ES2015块不会污染全球范围

另外,请记住并非所有浏览器都支持ES2015语法,所以现在必须使用Babel JS或类似工具来编译代码。

答案 2 :(得分:0)

这是因为location已在全局范围内声明为window.location

为了避免这种情况,这段代码不应该在本地范围内执行,即一个块。这是ES6,而IIFE则是ES5的遗留问题:

{
  ...
  const [{ location }] = companies; 
}

ES6的典型用途是模块化环境。考虑到当前范围是CommonJS或ES6模块,问题将永远不会出现。

答案 3 :(得分:-3)

const companies = [
  { name: 'Google', location: 'Mountain View' },
  { name: 'Facebook', location: 'Menlo Park' },
  { name: 'Uber', location: 'San Francisco' }
];

console.log(companies[0].location);