昨天工作之中,前端伙伴討論到了解構賦值到底是淺拷貝還是深拷貝,今天梳理一下。
1、ES6的解構賦值,大家應該都清楚,就是可以快速取出數組或者對象中的值;具體使用情況如下:
const a = { name: 'name', age: 18, marriage: false, } let { name, age, marriage} = a; console.log(name, age, marriage)
打印信息:name 18 false
2、明確一下深拷貝和淺拷貝的定義,或者說深拷貝和淺拷貝所應用於的數據類型。
深拷貝:修改新變量的值不會影響原有變量的值。默認情況下基本數據類型(number,string,null,undefined,boolean)都是深拷貝。
淺拷貝:修改新變量的值會影響原有的變量的值。默認情況下引用類型(object)都是淺拷貝。
其實你只要理解透徹了這兩句話就應該明白了解構賦值,甚至深拷貝的原理;
寫兩個例子,理解一下深拷貝和淺拷貝;
2.1 基本數據類型,直接用等號賦值,也都是深拷貝;
let a = 1; let b = a; b = 2; console.log(a,b);
打印出:1,2
b的數值改變並不會影響a,所以基本數據類型賦值就是深拷貝;
2.2 引用類型,直接用等號賦值,是淺拷貝;
let a = { name: 'xiaoming' }; let b = a; b.name = 'zhangsan'; console.log(a)
打印:
發現a的數據被b改變,所以是淺拷貝,為什么數據會被改變呢?
因為他們引用的是同一個地址的數據!拷貝的時候並沒有給b創造獨立的內存,只是把a指向數據的 指針 拷貝給了b!(不做延伸,感興趣的同學自行百度)
3、回到解構賦值,改一下最上面的例子。
const a = { name: 'name', age: 18, marriage: false, } let { name, age, marriage} = a; name = 'name1'; age = 20; marriage = true; console.log(a)
打印:
發現a的數據並沒有被改變,解構賦值好像是深拷貝啊?????
我們再改一下上面的例子看看:
const a = { name: 'name', age: 18, marriage: false, addr: { province: 'sichuan', city: 'chengdu' } } let { name, age, marriage, addr } = a name = 'myname' age = 26 marriage = true addr.province = 'shanghai' addr.city = 'shanghai' console.log(name, age, marriage, addr) console.log(a)
打印:
發現解構賦值出來的對象將原對象a中的addr的數據修改了,這樣看還是淺拷貝;
總結:解構賦值,如果所解構的原對象是一維數組或對象,其本質就是對基本數據類型進行等號賦值,那它就是深拷貝;
如果是多維數組或對象,其本質就是對引用類型數據進項等號賦值,那它就是淺拷貝;
最終的結論就是:解構賦值是淺拷貝(因為它確實不能對多維數組或對象達到深拷貝的作用);
4、最后我們再看一下深拷貝的本質:
深拷貝的實現方法:
function deepClone(source){ const targetObj = source.constructor === Array ? [] : {}; // 判斷復制的目標是數組還是對象 for(let keys in source){ // 遍歷目標 if(source.hasOwnProperty(keys)){ if(source[keys] && typeof source[keys] === 'object'){ // 如果值是對象,就遞歸一下 targetObj[keys] = source[keys].constructor === Array ? [] : {}; targetObj[keys] = deepClone(source[keys]); }else{ // 如果不是,就直接賦值 targetObj[keys] = source[keys]; } } } return targetObj; }
主要看這個:
它的本質還是將對象拆開為基本數據類型進行賦值。