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效果最佳。

相关文章
相关标签/搜索