js中如何復制一個數組(淺復制、深復制)
在js中,我們經常會用到數組復制,Array是引用類型,如果用arrA=arrB簡單的把一個數組賦值,並沒有創造出一個新數組,arrA和arrB其實指向的還是同一個地址,改變一個另一個也會隨之改變,很明顯這並不是我們想要的
var arr = [1, 2, 3]; var newArr = arr; arr.push(4); console.log(newArr1); // [1, 2, 3, 4]
下面介紹數組的淺復制
(適用於數組並不復雜,即數組中沒有嵌套對象或者嵌套數組)
方法一:concat()
- concat()方法用於連接兩個或多個數組;
- concat() 方法不會更改現有數組,而是返回一個新數組,其中包含已連接數組的值。
var arr = [1, 2, 3]; var newArr = arr.concat(); arr.push(4); console.log(newArr); // [1, 2, 3]
方法二:slice()
- slice() 方法以新的數組對象,返回數組中被選中的元素;
- slice() 方法選擇從給定的 start 參數開始的元素,並在給定的 end 參數處結束,但不包括;
- slice() 方法不會改變原始數組;
var arr = [1, 2, 3]; var newArr = arr.slice(); arr[0] = 10; console.log(arr);// [10, 2, 3] console.log(newArr);// [1, 2, 3]
方法三:擴展運算符
var arr = [1, 2, 3]; var [ ...newArr ] = arr; arr[0] = 10; console.log(arr); // [10, 2, 3] console.log(newArr);// [1, 2, 3]
方法四: Object.assign()
var arr = [1, 2, 3]; var newArr = Object.assign([], arr); arr[0] = 10; console.log(arr);// [10, 2, 3] console.log(newArr);// [1, 2, 3]
如果數組元素是對象或者數組,上面四種方法就會隻拷貝數組或者對象的引用,如果我們對其中一個數組進行修改,另一個數組也會發生變化
比如:
var arr = [ { a: 1 }, [ 1, 2 ], 3 ]; let newArr = arr.concat(); arr[0].a = 2; console.log(arr); // [ { a: 2 }, [ 1, 2 ], 3 ] console.log(newArr);// [ { a: 2 }, [ 1, 2 ], 3 ] 值被影響
下面是深復制
(可以完全拷貝一個數組,即使嵌套瞭對象或者數組,兩者也不會互相影響)
方法一:JSON.parse(JSON.stringify(arr))
var arr = [ { a: 1 }, [ 1, 2 ], 3 ]; // let newArr = JSON.parse(JSON.stringify(arr)); let newArr = arr.concat(); arr[0].a = 2; console.log(arr); // [ { a: 2 }, [ 1, 2 ], 3 ] console.log(newArr);// [ { a: 1 }, [ 1, 2 ], 3 ]
但是該方法是有局限性的
- 會忽略 undefined
- 會忽略 symbol
- 不能序列化函數
- 不能解決循環引用的對象
比如下面這個例子:
let a = { age: undefined, sex: Symbol('male'), jobs: function() {}, name: 'sun' } let b = JSON.parse(JSON.stringify(a)) console.log(b) // {name: "sun"}
方法二:通用方法(數組或對象)
拷貝的時候判斷屬性值的類型,如果是對象,繼續遞歸調用深拷貝函數(簡易版)
var deepCopy = function(obj) { // 判斷是否是對象 if (typeof obj !== 'object') return; // 判斷obj類型,根據類型新建一個對象或者數組 var newObj = obj instanceof Array ? [] : {} // 遍歷對象,進行賦值 for (var key in obj) { if (obj.hasOwnProperty(key)) { let val = obj[key]; // 判斷屬性值的類型,如果是對象,遞歸調用deepCopy newObj[key] = typeof val === 'object' ? deepCopy(val) : val } } return newObj }
方法三:利用lodash的深拷貝函數
_.cloneDeep(value)
其中value就是要深拷貝的值
簡單例子
var objects = [{ 'a': 1 }, { 'b': 2 }]; var deep = _.cloneDeep(objects); console.log(deep[0] === objects[0]); // => false
在Vue中使用
安裝
npm i --save lodash
在main.js中引入
import _ from 'lodash'; Vue.prototype._ = _;
使用
let newObj = this._.cloneDeep(oldObj)
總結
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- javascript進階篇深拷貝實現的四種方式
- 老生常談JavaScript深拷貝與淺拷貝
- JavaScript中深拷貝與淺拷貝詳解
- JS的深淺復制詳細
- JavaScript 賦值,淺復制和深復制的區別