這是一篇記錄『深入淺出 JS30 Day 14:JavaScript References VS Copying』 的筆記文章, 這個觀念在各大筆式都很常被考到, 所以搞懂它, 擁抱它, 是一件很重要的事情, 底下問題的答案, 都放到excel檔裡面, 都寫對了, 才算是瞭解了.
原始題目
要先有值, 才能賦值.
數字, 字串, Null, undefined, boolean
1 2 3 4
| let e = true let f = e e = !f console.log(e, f)
|
難度加強
1 2 3 4 5 6 7
| let g = 'A' let h = 'A' let i = 'A'
(h = 'B'), (i = 'C'), (g += h), (g += i) console.log(g, h, i)
|
陣列
1 2 3 4
| let players = ['Wes', 'Sarah', 'Ryan', 'Poppy']; let players2 = players; players2[0] = "alex" console.log(players, players2);
|
陣列實作淺拷貝
slice
1 2 3
| const players = ['Wes', 'Sarah', 'Ryan', 'Poppy']; const team = players.slice() console.log(players === team)
|
concat
1 2 3
| const players = ['Wes', 'Sarah', 'Ryan', 'Poppy']; const team2 = [].concat(players) console.log(players === team2)
|
spread operator
(我自己最常用的方法)
1 2 3
| const players = ['Wes', 'Sarah', 'Ryan', 'Poppy']; const team3 = [...players] console.log(players === team3)
|
Array.from
這個方法也常用來把類陣列轉變為陣列的用法, 例如用在querySelectorAll的篩選器上使用.
1 2 3
| const players = ['Wes', 'Sarah', 'Ryan', 'Poppy']; const team4 = Array.from(players) console.log(players === team4)
|
難度加強
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function createObj(name){ return { name } }
let p1 = createObj('alex') let p2 = createObj('sara') let p3 = createObj('howard') let p4= createObj('thor')
let f1 = [p1, p2, p3, p4] let f2 = f1.slice()
f2[0].name = 'alexander'; console.log(f1[0].name)
f2[0] = { name: 'alexander' }; console.log(f1[0].name)
|
物件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| let person = { name: 'wes', age: 80 }
let p2 = person
person = 'xxx' console.log(person, p2)
person.name = 'xxx' console.log(person, p2)
|
實作淺拷貝
Object.assign({ }, target)
由後往前覆蓋
1 2 3 4 5 6 7
| let a = {name: 'alex', age: 36} let b = {name: 'sara'}
let c = Object.assign(a, b) console.log(c)
|
示範要增加key和value的用法
1 2 3 4 5 6 7
| const person = { name: 'Wes Bos', age: 80 };
const team6 = Object.assign({ }, person, {number: 99} ) console.log(team6)
|
JSON.parse(JSON.stringify(target))
先字串化, 再物件化, 用法同Object.assign({ }, target)
1 2 3 4 5 6
| let a = {name: 'alex', age: 36} let b = {name: 'sara'}
let c = JSON.parse(JSON.stringify)(a, b) console.log(c)
|
缺陷
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| let aa = { name: 'alex', age: 36, sayHi:function(){ console.log('hi') } }
aa.sayHi()
let bb = JSON.parse(JSON.stringify(aa)) bb.sayHi()
let cc = Object.assign({ }, aa) cc.sayHi()
|
那 aa.say === cc.say ?? 兩者function一樣嗎?
如果是不帶function的純data資料, JSON.parse可以做到深拷貝, 如果有帶可能就要用prototype
去做
難度加強
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| let wes = { name: 'wes', age: 80, social:{ facebook:'wes', twitter: 'wes developer' } }
let wes2 = Object.assign({ }, wes) wes2.social = null console.log(wes.social)
wes2.social.facebook = null console.log(wes.social)
let wes3 = JSON.parse(JSON.stringify(wes))
|
其餘範例
1 2 3 4 5 6 7 8 9 10
| let ary = [{a: 1}, {b: 2}, {c:3}] ary.forEach(item =>{ for(let key in item){ console.log(key, item[key]) } })
|
1 2 3 4 5 6 7 8 9 10
| let ary = [{a: 1}, {b: 2}, {c:3}] ary.forEach((item, index) =>{ Object.keys(item).forEach(key =>{ console.log(index, key, item[key]) }) })
|
結論
洋洋灑灑寫了一堆, 這場蠻值得的, 要常回來多看, 不敢說自己已經百分百掌握. 總之概念就是要先存值再賦值, 更深刻的講法是要有值才能賦值 , 往這個概念走就八九不離十, 存值比較重要的是, 如果沒有這個值, 得要開新的記憶體空間.
這邊再加強一個觀念
- 如果是簡單的賦值, 例如 players2 = players , 那新的players2, 在標記完位置後是要存players的值.
- 如果是淺拷貝, 例如players2 = JSON.parse(JSON.stringify(players)), 那新的players2, 在標記完位置是要存players的位置.
範例答案
此範例以Alex宅幹嘛的教學和wes bros為主