У меня есть простой массив объектов и я хочу получить атрибут местоположения первого элемента:

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

Чего мне не хватает?

7
StandardNerd 12 Янв 2017 в 16:57

4 ответа

Лучший ответ

Вы не можете переопределить глобальную переменную 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);
12
Juan Mendes 12 Янв 2017 в 19:23

Это происходит потому, что location уже объявлен в глобальной области видимости как window.location.

Чтобы избежать этого, этот фрагмент кода не должен выполняться в локальной области, то есть в блоке. Это ES6, а IIFE - это остатки ES5:

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

Типичное использование для ES6 - модульная среда. Учитывая, что текущая область действия - модуль CommonJS или ES6, проблема никогда не появится.

0
Estus Flask 12 Янв 2017 в 14:20

Проблема в том, что вы не заключаете свой код в функцию.

Если вы используете IIFE (выражение вызова с немедленным вызовом), тот же код будет работать.

Причина, по которой ваш код дает сбой, заключается в том, что вы не можете объявить константу в той же области видимости, если имя константы / переменной уже занято.

Вы могли бы использовать var вместо const, но это бы назначило window.location, эффективно перезагрузив страницу и перенеся вас на страницу 404, потому что этот URL не существует.

Вот почему вы всегда должны писать свой код в IIFE, чтобы предотвратить загрязнение глобального пространства имен и неприятные ошибки, которые трудно исправить.

Вот тот же код с IIFE (добавлен строгий режим):

(() => { // 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);
})();

Или еще лучше:

{ // 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);
};

Использование блока ES2015 не будет загрязнять глобальную область, поскольку вы будете использовать только let и const (а не var)

Кроме того, всегда помните, что не все браузеры поддерживают синтаксис ES2015, поэтому на данный момент код должен передаваться с использованием Babel JS или аналогичных инструментов.

5
Zorgatone 5 Апр 2017 в 09:52
const companies = [
  { name: 'Google', location: 'Mountain View' },
  { name: 'Facebook', location: 'Menlo Park' },
  { name: 'Uber', location: 'San Francisco' }
];

console.log(companies[0].location);
-3
Sharkuun 12 Янв 2017 в 14:04