1. 程式人生 > >JS中徹底弄懂淺拷貝和深拷貝

JS中徹底弄懂淺拷貝和深拷貝

1、淺拷貝和深拷貝的簡介

淺拷貝:兩個物件經過拷貝後雖然具有相同的屬性,但是他們都指向同一個記憶體空間

let a = {x: 123}
let b = a
b.x = 234
console.log(b)   // {x: 234}
console.log(a)   // {x: 234}

.操作會引起引用,同一地址的變數一起改變

深拷貝:兩個物件除了拷貝了一樣的屬性, 沒有任何其他關聯(指向不同的記憶體空間)。

2、深拷貝實現方法

(1). 物件深拷貝

a.普通物件(單層屬性)

方法1:ES5 for迴圈賦值

let souceObj = {x: 1, y: 2}

function clone(souceObj, targetObj = {}) {
    for (const key in souceObj) {
        targetObj[key] = souceObj[key]
    }

    return targetObj
}

let targetObj = clone(souceObj)
targetObj.x = 10
console.log(souceObj)   //{ x: 1, y: 2 }
console.log(targetObj)  //{ x: 10, y: 2 }

方法2:JSON parse stringify

let souceObj = {x: 1, y: 2}
let targetObj = JSON.parse(JSON.stringify(souceObj))
targetObj.x = 10
console.log(souceObj)   //{ x: 1, y: 2 }
console.log(targetObj)  //{ x: 10, y: 2 }

方法3:ES6 操作符 ...

let souceObj = {x: 1, y: 2}
let targetObj = {...souceObj}
targetObj.x = 10
console.log(souceObj)   //{ x: 1, y: 2 }
console.log(targetObj)  //{ x: 10, y: 2 }

方法4:ES6  Object.assign()

let souceObj = {x: 1, y: 2}
let targetObj = Object.assign({}, souceObj)
targetObj.x = 10
console.log(souceObj)   //{ x: 1, y: 2 }
console.log(targetObj)  //{ x: 10, y: 2 }

b.巢狀物件(多層屬性:屬性也是物件)

function deepCopy(source, target = {}) {
    let key;
    for (key in source) {
	    // 意思就是__proto__上面的屬性,我不拷貝
        if (source.hasOwnProperty(key)) {      
			// 如果這一項是object型別,就遞迴呼叫deepCopy
            if (typeof(source[key]) === "object") {                                          
                target[key] = Array.isArray(source[key]) ? [] : {};
                deepCopy(source[key], target[key]);
            } else {      
				// 如果不是object型別,就直接賦值拷貝
                target[key] = source[key];
            }
        }
    }
    return target;
}

(2). 陣列深拷貝

方法1: 陣列的  slice方法

let souceArr = ['one', 'two', 'three']
let targetArr = souceArr.slice(0)
targetArr[1] = 'new two'
console.log(souceArr)   //[ 'one', 'two', 'three' ]
console.log(targetArr)  //[ 'one', 'new two', 'three' ]

方法2: 陣列的  concat方法

let souceArr = ['one', 'two', 'three']
let targetArr = souceArr.concat()
targetArr[1] = 'new two'
console.log(souceArr)   //[ 'one', 'two', 'three' ]
console.log(targetArr)  //[ 'one', 'new two', 'three' ]

物件陣列的深拷貝:

let souceArr = [{'name': 'weifeng'},{'name': 'boy'}];//原陣列

[].concat(JSON.parse(JSON.stringify(souceArr)))

方法3: ES6 操作符 ...

let souceArr = ['one', 'two', 'three']
let targetArr = [...souceArr]
targetArr[1] = 'new two'
console.log(souceArr)   //[ 'one', 'two', 'three' ]
console.log(targetArr)  //[ 'one', 'new two', 'three' ]

方法4: 基礎方法 迴圈遍歷

這裡就不貼程式碼了...