js的淺拷貝和深拷貝

常常遇到數組或對象等引用類型做爲函數的參數的狀況,但又不想修改原來的數據,這時候就須要拷貝(基本類型的變量不須要考慮)。
拷貝分爲淺拷貝深拷貝。淺拷貝是引用複製,深拷貝是徹底單純拷貝數據的值。由於數組是最多見的引用類型,因此下面大部分拿數組舉例。git

  • 淺拷貝

  • 簡單把引用複製
var a = [1,2,3]
var b = a
console.log(b) //Array(3) [1, 2, 3]
b[1] = 0
console.log(b) //Array(3) [1, 0, 3]
console.log(a) //Array(3) [1, 0, 3]

能夠看出,修改數組b的時候,數組a也被修改了。這顯然不是想要的作法。es6

要想不改變原來的數組,就要用到如下的幾種方法:github

var a = [1,2,3]
var b = a.concat() //或 var b = [].concat(a)
console.log(b) //Array(3) [1, 2, 3]
b[1] = 0
console.log(b) //Array(3) [1, 0, 3]
console.log(a) //Array(3) [1, 2, 3]
var a = [1,2,3,4,5]
var b = a.slice(0)
console.log(b) //Array(5) [1, 2, 3, 4, 5]
b[0] = 0
console.log(a) //Array(5) [1, 2, 3, 4, 5]
console.log(b) //Array(5) [0, 2, 3, 4, 5]

還能夠部分拷貝json

var a = [1,2,3,4,5]
var b = a.slice(1, 3) //返回[1,3)下標區間的數
console.log(b) //Array(2) [2, 3]
//負數也能夠
console.log(a.slice(-2)) //Array(2) [4, 5]

還有一種方法,跟循環的方法有點相似,就是es6的新特性,展開語法數組

var a = [1,2,3,4,5]
var b = [...a]
b[0] = 0
console.log(a) //Array(5) [1, 2, 3, 4, 5]

這個方法就是逐一枚舉a中的值,放到空數組中函數

可是,以上這幾種拷貝方法看似都不會改變原來數組,其實也仍是屬於淺拷貝範疇。若是原數組裏面還有引用類型數組,這些方法都會失效(好比二維數組)code

var a = [[1,2,3],[4,5,6]]
var b = a.slice(0)
b[0][4] = 0
console.log(a[0]) //[[1, 2, 0],[4,5,6]]

其餘concat,[...]等方法也同樣。
能夠這麼理解:原數組就像一個帶鎖的獨一無二的箱子,裏面有各類零食。簡單的引用複製,其實就是配了一把鑰匙,誰動過裏面的東西,其餘人都會受到影響。而上面這4種方法其實就是本身買一個不一樣箱子,參照原來的箱子裏面的零食,去某寶買同款。動本身箱子的東西,原來的箱子不受影響。可是若是原來的箱子裏面還套了個獨一無二帶鎖的箱子,某寶買不到同款,那沒辦法,裏面的箱子只能仍是配把鑰匙共用。因此,這4種方法只是簡單繞過第一層箱子的引用複製對象


  • 深拷貝

目前比較好的方法就是json大法JSON.stringify(),要麼就是本身寫遞歸的深拷貝函數。
JSON.stringify()是將對象或數組序列化成字符串。而後再用JSON.parse()解析成值或對象。遞歸

var a = {aa:1,bb:[1,2],cc:[3,4]}
var b = JSON.parse(JSON.stringify(a))
console.log(b) //{aa:1,bb:[1,2],cc:[3,4]}
b.cc[0] = 0
console.log(a) //{aa:1,bb:[1,2],cc:[3,4]}
console.log(b) //{aa:1,bb:[1,2],cc:[0,4]}

附帶深拷貝的自定義函數(源自大佬mqyqingfeng的github)ip

var deepCopy = function(obj) {
    if (typeof obj !== 'object') return;
    var newObj = obj instanceof Array ? [] : {};
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
        }
    }
    return newObj;
}
相關文章
相關標籤/搜索