注册

JS中的深拷贝和浅拷贝

作者:admin - 时间:18-04-03 09:57 - 阅读量:13 - 评论:0

JS对象的分类

JS中对象分为基本类型和复合(引用)类型,基本类型存放在栈内存,复合(引用)类型存放在堆内存。

堆内存用于存放由new创建的对象,栈内存存放一些基本类型的变量和对象的引用变量。

一个简单对象

先定义一个简单对象,后续的例子都基于该对象。

var obj = {
    a:1,
   arr:[2,3] 
};

浅拷贝

首先深拷贝和浅拷贝只针对像 Object, Array 这样的复杂对象的。浅拷贝只复制一层对象的属性。

  • 方法一: 简单的对对象的属性进行遍历,然后分别赋值给另一个对象。
// 定义复制的方法
function clone(obj){
    var _obj = {};
   for(var key in obj){ 
   // 这里先不考虑原型链上的属性
   if(obj.hasOwnProperty(key)){  
          _obj[key] = obj[key];
         }
   } 
   return _obj;
}

// 调用这个clone方法
var shadowObj = clone(obj);
  • 方法二:

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

// 定义复制的方法
function clone(obj){
    var _obj = Object.assign({},obj);
   return _obj; 
}

// 调用这个clone方法
var shadowObj = clone(obj);

浅拷贝只会将对象的各个属性进行复制,但对象内的数组或对象,只会复制其引用,使其指向同一个内存地址。 所以: obj.arr shallowObj.arr 指向同一块内存地址。

图示如下:

其导致的结果:

shallowObj.arr.push(4);
obj.arr();  // [2,3,4]
// 会对原来的对象产生影响

深拷贝

而深拷贝则不同,它不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深拷贝的方法递归复制到新对象上。 所以: 修改一个对象的属性,不会改变另一个对象的属性。

  • 方法一: 使用 JSON.parse() 方法 这种方式比较简单,但是如果属性的值为undefined,或者属性值为一个函数,那么就会被过滤掉。
// 定义复制的方法
function clone(obj){
    var _obj = JSON.parse(JSON.stringify(obj));
   return _obj; 
}

// 调用深拷贝的方法
var deepObj = clone(obj);
  • 方法二: 递归拷贝
// 定义复制的方法
function clone(obj){
    if(!obj || typeof obj !== 'object'){
        return;
    }
    var _obj = obj.constructor === Object ? {} : [];
    for(var key in obj){
        _obj[key] = obj[key] && (typeof obj[key] === 'object' ? clone(obj[key]) : obj[key]);
    }
    return _obj;
}

// 调用深拷贝的方法
var deepObj = clone(obj);
评论 一共有0条评论



登 录
注 册