2017-01-12 22 views
4

我有對象的簡單數組,並希望得到的第一個元素的位置屬性:的Javascript ES6解構 - 標識符「位置」已經聲明

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

我是什麼失蹤?

回答

9

您不能將全局變量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

我澄清了一句:「你不能重新定義全局變量X」,一般只適用於在同一範圍內的常數。你可以寫更多'var'相同的聲明,雖然 – Zorgatone

+0

我不明白你的意思。我說的是什麼問題,以及哪些代碼會給你提供那個錯誤? OP在「位置」變量而不是「公司」變量方面存在問題 – Zorgatone

+0

好吧,我看到您添加了代碼。讓我先讀它 – Zorgatone

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

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

這裏的問題是,你不換一個函數內部代碼。

如果使用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); 
 
};

釷E使用ES2015塊不會污染全球範圍內,因爲你將只使用letconst(而不是使用var

此外,永遠記住,不是所有的瀏覽器都支持ES2015還沒有語法,所以目前代碼必須使用Babel JS或類似工具進行傳輸。

+0

說:'希望得到的第一個元素的位置屬性:'還要注意從estus的評論,應該使用塊,因爲它的ES6 – Zorgatone

+0

OP與胡安·門德斯代碼後回答@Sukima更新答案 –

+0

你是對的。我錯過了一個 – Zorgatone

0

這是因爲location已經宣佈全球範圍內,爲window.location

爲了避免這種情況,這一段代碼不應該在本地範圍內被執行,即,一個塊。這是ES6,而IIFE是ES5的剩餘部分:

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

ES6的典型用途是模塊化環境。考慮到目前的範圍是CommonJS或ES6模塊,問題將不會出現。

+0

請,還要注意'ES2015塊範圍內var'無論如何都會污染在全球範圍內,所以你必須只使用'const'和'let' – Zorgatone

+0

@Zorgatone這是正確的。一般來說,最好不要使用'var',因爲它會產生比解決問題更多的問題。由於這個原因,ESLint中有'no-var'規則。 – estus

+0

我評論過只是爲了說明一下。確實,在ES6中只使用'const'和'let'是很好的做法。但只是爲了警告在小組中工作時要小心,或者在不檢查其他來源的情況下複製粘貼代碼,如果同一變量未聲明超過一次,則不包含任何'var'並用'let'替換 – Zorgatone