Js之淺拷貝深拷貝與對象數組的遍歷

在js這門語言中,數據存放在堆中,而數據的引用的存放在棧中。數組

淺拷貝

咱們說的淺拷貝,指的是,引用地址的拷貝,棧中兩塊不一樣的引用地址都指向了堆中一樣一塊區域。因此,咱們經過一個地址修改了堆中的數據,另一個引用的地址一樣會改變。數據結構

淺拷貝的常見寫法有直接複製賦值,使用Object.assign()也是淺拷貝。函數

let obj = {
    'a':1,
    'b':2,
    'c':{
        'c1':3,
        'c2':4
    }
}
obj.b = 22

let newObj = obj
let newObj2 = Object.assign({},obj)

console.log(newObj)    // newObj.b爲22
console.log(newObj2)   // newObj.b也爲22

深拷貝

和淺拷貝不一樣的是,深拷貝是單獨開闢一段堆內存空間,把以前堆內存中的對象複製,這樣在棧內存的新的引用會指向新的堆內存空間,新老兩塊空間彼此並無直接的聯繫,這樣的話,咱們修改了以前的對象,新拷貝的對象並不會隨之改變。code

常見的深拷貝方法有兩種,一種是遞歸,另一種是JSON序列化。對象

function deepCopy(obj){
    let newObj = obj.constructor === Array ? []: {}   //判斷是深拷貝對象仍是數組
    
    for(let i in obj){
        if(typeof obj[i] === 'object') {
            newObj[i] = deepCopy(obj[i])    //  若是要拷貝的對象的屬性依然是個複合類型,遞歸
        } else {
            newObj[i] = obj[i]
        }
    }
    
    return newObj
}

let obj = {
    'a':1,
    'b':2,
    'c':{
        'c1':3,
        'c2':4
    }
}
let arr = [1,2,3,[4,5,6],7]

let newObj = deepCopy(obj)
let newArr = deepCopy(arr)

obj.b = 22
arr[3][1] = 55

console.log(obj.b,newObj.b)     // 22 2
console.log(arr[3][1],newArr[3][1])   //55 5

運用遞歸,當要拷貝的對象或者數組的屬性依然是個對象或者數組時,遞歸調用。繼承

除了遞歸的方式,使用JSON序列化能夠很方便的解決深拷貝問題。遞歸

// 依然使用上面的例子
let newObj = JSON.parse(JSON.stringify(obj))

這種方法很巧妙很簡單,可是,侷限性在於不能拷貝繼承的屬性,原型中的屬性。只有在一些簡單的場合才推薦使用。接口

遍歷對象

聊完了深拷貝和淺拷貝,接下來講一下遍歷。由於咱們發現,上面深拷貝的時候執行遞歸的時候,採用的是for ...in的遍歷方式。內存

除了for...in,在js中的遍歷方式還有不少,好比Object.keys(),for...of等等,那麼這些遍歷方式有什麼不一樣呢。字符串

Object.keys()

這個方法用於遍歷,可以遍歷出來的東西是對象中全部的可枚舉的屬性,可是不包括繼承過來了。

for...in

for...in通常用於遍歷對象,可以返回對象包括繼承過來的可枚舉屬性。

Object.getOwnPropertyNames(obj)

返回對象全部的屬性,也包括不可枚舉的屬性。可是不包括繼承過來的。
這個函數會返回一個數組。

這三個遍歷對象的方法,都不會返回對象中的symbol屬性。

遍歷數組

和遍歷對象不一樣,遍歷數組也有一些方法。

for...in

for...in除了能夠遍歷對象,也能夠遍歷數組,因此上面的例子咱們能夠用for...in分別遍歷對象和數組。

forEach()

這是ES5新提供的一個方法,接收一個函數做爲參數,回調函數。

for...of

ES6提供的遍歷器,除了能夠遍歷數組,還支持類數組對象,甚至是字符串,其實就是繼承了Iterator接口的數據結構均可以用for...of來遍歷。

for...of循環可使用的範圍包括數組、Set 和 Map 結構、某些相似數組的對象(好比arguments對象、DOM NodeList 對象)、後文的 Generator 對象,以及字符串。

我認爲,遍歷數組,使用for...of效果最佳。

相關文章
相關標籤/搜索