Star Warsで解説
starwars.js
const episode1 = [
{ name: 'Anakin', jedi: true },
{ name: 'Luku', jedi: true }
]
const episode3 = episode1.map(char => char)
// Dirk side
episode3[0].jedi = false
console.log(episode1)
// [ { name: 'Anakin', jedi: false },{ name: 'Luku', jedi: false } ]
console.log(episode3)
// [ { name: 'Anakin', jedi: false },{ name: 'Luku', jedi: true } ]
アナキンはエピソード3でダークサイドに墜ちるのでjedi = false
に変更。
...あれ、episode1でシスに落ちとるがな、ストーリー上ありえないので修正
答えから言うとmap, filterは中のオブジェクトまでは写像しない!
starwars.js
const episode1 = [
{ name: 'Anakin', jedi: true },
{ name: 'Luku',
jedi: false }
]
const episode3 = episode1.map(char => Object.assign({}, char))
// Dirk side
episode3[0].jedi = false
console.log(episode1)
// [ { name: 'Anakin', jedi: true },{ name: 'Luku', jedi: false } ]
console.log(episode3)
// [ { name: 'Anakin', jedi: false },{ name: 'Luku', jedi: false } ]
Object.assign()
でオブジェクト自体も新しいものを作ってあげると解決!
無事ストーリーが進みそう。
filterでもはまった
jediだけを抽出し配列を作る。前回の反省にならってObject.assign()
を使う。
starwars.js
const episode1 = [
{ name: 'Anakin', jedi: true },
{ name: 'Luku', jedi: true },
{ name: 'Amidala', jedi: false }
]
const episode3 = episode1.filter(char => {
if (char.jedi) {
return Object.assign({}, char)
}
})
// Dirk side
episode3[0].jedi = false
console.log(episode1)
// [ { name: 'Anakin', jedi: false }, { name: 'Luku', jedi: true }, { name: 'Amidala', jedi: false } ]
console.log(episode3)
// [ { name: 'Anakin', jedi: false }, { name: 'Luku', jedi: true } ]
アナキンがシスになってる...
ジェダイ図書館で調べたところ、
filterは値が偽の場合値を返さない
真の場合値をそのまま返す。
つまりObject.assign
は実行されていない。
これはおったまげ、ジャージャーが非常事態にパルパティーンに武力行使権を与えるのも納得。
解決法
starwars.js
const episode1 = [
{ name: 'Anakin', jedi: true },
{ name: 'Luku', jedi: true },
{ name: 'Amidala', jedi: false }
]
const episode3 = episode1.filter(char => {
if (char.jedi) {
return char
}
}).map(char => Object.assign({}, char))
// Dirk side
episode3[0].jedi = false
console.log(episode1)
// [ { name: 'Anakin', jedi: true }, { name: 'Luku', jedi: true }, { name: 'Amidala', jedi: false } ]
console.log(episode3)
// [ { name: 'Anakin', jedi: false }, { name: 'Luku', jedi: true } ]
なるほど、filterにmapを連結して新しい配列を返す。
ジェダイ・マスターへの道は遠い...