浅拷贝:指向同一个记忆体,原始值与新複製出来的值会连动深拷贝:为切断之间的关联性,複製即产生一个新的记忆体存放,所以当改动複製出来的值时,原始值就不会随着被更动在js中,物件与阵列的複製皆属于call by reference,所以如果以原始型别複製的方法,会有改写原始值的问题
//原始型别如数值let a = 7 let b = aa = 8console.log(a, b) //8, 7
由于原始型别複製是call by value(参考值,但创自己新的记忆体空间,指向的位置不同,所以改变a对b不会有影响)但在阵列複製是call by reference的情况下:const players = ['emma', 'wilee', 'stella', 'jenny']const team = playersteam[3] = 'julia'console.log(players, team)// ['emma', 'wilee', 'stella', 'julia']// ['emma', 'wilee', 'stella', 'julia']
team一改,players会跟着改,因为两个物件指向同一个记忆体,基本上他们两个是同一个东西,只是用不同名称来称呼同一个东西阵列如何切断连动关係,实现深拷贝const players = ['emma', 'wilee', 'howord', 'jenny']const team2 = [...players]const team3 = [].concat(players)const team4 = Array.from(players)cosnt team5 = players.slice()team5[3] = 'julia'team2[3] = 'cash'team3[3] = 'miya'team4[3] = 'sylar'console.log(players, team2, team3, team4, team5);// ['emma', 'wilee', 'stella', 'jenny']// ['emma', 'wilee', 'stella', 'cash']// ['emma', 'wilee', 'stella', 'miya']// ['emma', 'wilee', 'stella', 'sylar']// ['emma', 'wilee', 'stella', 'julia']以上四种方法都可以让複製值存放在新的记忆体,互相不干扰
接下来看物件,同样是call by reference,但深拷贝较複杂,易混淆const person = {name: 'julia'age: 40}const driver = persondriver.gentle = 'female'console.log(person, driver)//可以看到原本的person跟driver连动
用以下这两种作法看是否能达到深拷贝Object.assign()... spread syntaxconst person = {name: 'julia',age: 40}const driver = Object.assign({}, person)driver.name = 'stella'const driver2 = {...person}driver2.name = 'amy'console.log(person, driver, driver2)//看起来似乎有成功但...
如果物件内又包一个物件(nested object),其物件仍指向同一个记忆体,所以这2种做法只达到最外层深拷贝,里面还是一样,const julia = { name: 'julia', age: 40, social: { facebook: '@aaa', instagram: '@bbb' } } const dev = Object.assign({}, julia) dev.social.instagram = '@ccc' console.log(julia, dev); //可以看到两个instagram连动 //...也是得到一样连动的结果
JSON.parse(JSON.stringfy())解决上面连动问题,达到深拷贝效果然而有两个雷物件中有function物件中有型别问题时参考影片:JavaScript Objects: Shallow and Deep Copy | All You Need to Know in 10 mins!如果发生上述两种情况,只能额外安装lodash解决const julia = { name: 'julia', age: 40, social: { facebook: '@aaa', instagram: '@bbb' } } const dev = JSON.parse(JSON.stringfy(julia)) dev.social.instagram = '@ccc' console.log(julia, dev);