2017-01-06 63 views
1

我在查找爲什麼persons數組包含新的age鍵:值對時遇到了一些問題。
我認爲通過切片(因此創建一個獨立的副本)我可以單獨在newArray上工作,只能附加age它......但它似乎更新persons以及??
在此先感謝Javascript:在切片和附加鍵後重複數組不正確

const persons = [ 
 
    { first: 'Albert', last: 'Einstein', birthYear: 1879, deathYear: 1955 }, 
 
    { first: 'Isaac', last: 'Newton', birthYear: 1643, deathYear: 1727 }, 
 
    { first: 'Galileo', last: 'Galilei', birthYear: 1564, deathYear: 1642 }, 
 
    ]; 
 

 
function appendAge(originalArray) { 
 
    var newArray = originalArray.slice(0); 
 

 
    newArray.forEach(item => { 
 
    item['age'] = item.deathYear - item.birthYear; 
 
    }) 
 
    return newArray 
 
} 
 
console.info(persons) 
 
var newPersons = appendAge(persons) 
 
console.info(newPersons)

回答

3

slice不淺拷貝,這意味着它僅複製值的頂層,包括參考,並不實際拷貝的參考價值本身。

這意味着你的兩個數組中的每個人對象都是同一個對象。

一個簡單的解決方案是爲您的人物對象創建一個自定義複製功能,並將其與map一起用於複製數組。

const people = [ 
 
    { first: 'Albert', last: 'Einstein', birthYear: 1879, deathYear: 1955 }, 
 
    { first: 'Isaac', last: 'Newton', birthYear: 1643, deathYear: 1727 }, 
 
    { first: 'Galileo', last: 'Galilei', birthYear: 1564, deathYear: 1642 }, 
 
    ]; 
 

 
function copyPerson(person) { 
 
    return Object.assign({}, person); 
 
} 
 

 
function copyPeople(people) { 
 
    return people.map(copyPerson); 
 
} 
 

 
function appendAge(people) { 
 
    const newArray = copyPeople(people); 
 

 
    newArray.forEach(item => { 
 
    item['age'] = item.deathYear - item.birthYear; 
 
    }); 
 

 
    return newArray; 
 
} 
 

 
console.info('----------------------------------------'); 
 
console.info('Old People'); 
 
console.log(people) 
 
console.info('----------------------------------------'); 
 
console.info('New People'); 
 
console.log(appendAge(people));

您還可以檢查出How do I correctly clone an object in JavaScript其他的解決方案。

+0

因爲'.map()'創建了一個新數組,所以如果您也調用'.map()',則不需要使用'.slice()'。 – Barmar

+0

@Barmar你是對的,我的不好,現在修好了 – nem035

+0

真棒...感謝超級快速的回覆......我讀了一些關於淺與深的副本,但並沒有真正去掌握它。 ..這個解決方案是完美的。 – sigmazen

3

您已創建persons數組的副本,其中包含對原始對象的引用,而不是這些對象的副本。要創建完整副本,您還需要克隆這些對象。

請注意,Object#assign將只複製對象的頂級屬性,因此您需要改爲對象deep clone

const persons = [ 
 
    { first: 'Albert', last: 'Einstein', birthYear: 1879, deathYear: 1955 }, 
 
    { first: 'Isaac', last: 'Newton', birthYear: 1643, deathYear: 1727 }, 
 
    { first: 'Galileo', last: 'Galilei', birthYear: 1564, deathYear: 1642 }, 
 
    ]; 
 

 
function appendAge(originalArray) { 
 
    return originalArray.map((item) => Object.assign({}, item, { 
 
    age: item.deathYear - item.birthYear 
 
    })); 
 
} 
 

 
var newPersons = appendAge(persons); 
 
console.info(newPersons); 
 
console.info(persons); // persons haven't changed

+0

爲什麼'Object.assign',爲什麼不簡單'originalArray.map(item =>({age:item.deathYear - item.birthYear}))'? – DavidDomain

+1

@DavidDomain,因爲OP想爲每個複製的人添加「age」作爲新屬性,而不是覆蓋整個person對象。 – nem035

+0

哦,對不起,認爲只有年齡需要在新的陣列,我的壞。 – DavidDomain

1

你.forEach循環實際上是什麼更新數組,而不是切片。切片正在製作副本,但當您傳遞它時,它會進入forEach循環。因此,當您將商品添加到您認爲是該副本的商品時,就會添加到原件中。

+0

我認爲這回答你的問題。我想我不明白你爲什麼要更新副本。也許你在做比較?如果是這樣,請對原始文件進行深層克隆,在初始化時將其存儲到變量中,然後在保存/更新比較orig時更新...只是在這裏猜測 –