很久沒寫文章了,都感受本身最近沒什麼進步啊,正愁不知道寫什麼呢,
這兩天的工做中偶然發現一個js數組深拷貝的問題,正好能夠拿出來講一說。數組
const arr = [{name: 'wens'},{age: '26'}]; //原數組 const newArr1 = arr.slice(0); const newArr2 = arr.concat();
newArr2[0].name = 'leon'; newArr2[1].age = '27';
在控制檯打印以後發現,尼瑪arr,newArr1,newArr2打印的東西徹底同樣,徹底同樣,徹底同樣spa
[{name: 'leon'},{age: '27'}];
說好的對數組進行slice或concat操做都是拿出一塊新的內存空間存放新的數組,而不是對原數組的引用呢。難道以前咱們對數組的深拷貝都被「騙了」。。。
別擔憂,下面,咱們一步步來分析分析翻譯
拋開slice,concat方法不說,最原始複製一個數組的方法是什麼code
var arr = [1,2,3] var newArr = arr
優勢:方便
缺點:因爲數組是引用類型(不懂基本類型和引用類型的自行補課),修改了arr或者newArr中的一個會影響所有對象
既然你們都知道賦值的缺點,因此纔有了slice,concat方法。
重點來了,搬好小板凳作好聽課:blog
slice 不修改原數組,只會返回一個淺複製了原數組中的元素的一個新數組。原數組的元素會按照下述規則拷貝:
若是該元素是個對象引用 (不是實際的對象),slice 會拷貝這個對象引用到新的數組裏。兩個對象引用都引用了同一個對象。若是被引用的對象發生改變,則新的和原來的數組中的這個元素也會發生改變。
對於字符串、數字及布爾值來講(不是 String、Number 或者 Boolean 對象),slice 會拷貝這些值到新的數組裏。在別的數組裏修改這些字符串或數字或是布爾值,將不會影響另外一個數組。
若是向兩個數組任一中添加了新元素,則另外一個不會受到影響。ip
引用MDN中的話,翻譯成白話:
數組中的值若是是引用類型,對其進行增刪改,會影響用slice複製的數組,
可是若是數組中的值是基本類型,就不會影響
如今回頭看開篇提出的那個問題,就很好理解了,由於數組裏面是obj,而obj是引用類型,因此固然修改了newArr,arr裏面的值也修改了
其實,工做中遇到的不少奇奇怪怪的問題大部分都是對知識點的模棱兩可,仔細看文檔就能解決的問題,因此說學好技術有時候並無你們想的那麼簡單,仔細仔細仔細,認真認真認真能作到這兩點的人好少啊內存
一、簡單粗暴:文檔
newArr1 = JSON.parse(JSON.stringify(arr));
這種方式可以知足99%的深拷貝(如開篇的例子),可是對與RegExp類型和Function類型則沒法徹底知足,並且不支持有循環引用的對象。字符串
二、現成的lodash庫:_.cloneDeep