首页 » JavaScript » javascript中的深拷贝和浅拷贝<整理>

javascript中的深拷贝和浅拷贝<整理>

原文 http://blog.csdn.net/weixin_37064409/article/details/79229194

2018-02-02 02:00:11阅读(495)

javascript中对数据的clone分为赋值、深拷贝和浅拷贝。
在经过克隆之后,我们希望clone的对象操作之后与数据源互不干扰。

在分析深拷贝和浅拷贝之前还有一个概念要清楚,就是不同数据类型的clone方式和效果是不同的。

javascript中数据类型 类型 内容 基本数据类型 string、number、boolean、null、undefined 引用类型 array、object、 基本数据类型保存在 栈 中,在进行浅拷贝操作后,会在内存中开辟一块新的空间,然后把赋过来的值保存于这块新开辟的空间中,存放在栈中的数据互不影响 引用数据类型保存在 堆 中,在进行浅拷贝操作后,也会开辟一块新的空间,不同的是新的空间保存的是赋值对象现在的地址,由于数据对地址的引用是相同的,所以会联动变化 所以深拷贝和浅拷贝是针对与引用类型讨论的 浅复制只复制一层对象的属性,而深复制则递归复制了所有层级。 赋值 如果只是想要对数据的复制,那么直接赋值就可以了,这是对数据进行clone的一种方式:
var data = {
    a : "hello",
    b : 12,
    c : [1,2,3],
    d : function(){
        return this.a;
    } 
}
var shallowcopy  = data;
console.log(shallowcopy);   //{a: "hello", b: 12, c: Array(3), d: ƒ};
但是这样会存在一个问题!
data.a += "world";
shallowcopy.a; //"hello"  
data.c.push(12);
shallowcopy.c  // [1, 2, 3, 12]  
① 当data.a变化时,shallowcopy.a不会跟着变化,这是我们想要的结果 ② 当data.c变化时, shallowcopy.cc也会跟着联动变化,和我们的需求不太一样。

所以有了浅拷贝的需求,使得拷贝出来的数据更新时和源数据互不干扰。

浅拷贝

方式一: splice()

slice() 方法返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象。原始数组不会被修改。
var arr = [1,2,3];
var arr1 = arr.slice(0);
arr.push(12);
arr //[1,2,3,12]
arr1 //[1,2,3]
由于slice()是数组的方法,所以这种方式只能对引用类型中的数组使用

方式二:Object.assign()

方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
Object.assign(target, …sources)
var arr = [1,2,3,4];
var arr2 =Object.assign([],arr); 
arr.a.push(12) 
arr2  //  Object { a: Array [1, 2, 3, 4, 12] }

// 这种浅拷贝方式,可操作所有引用类型的对象。且新对象与原对象互不干扰。但是新的问题出现了:

var obj = {
    a : [1,2,3,4],
    b : [5,6,7,8]   
}
var newobj = Object.assign({},obj);
obj.a.push(12)
newobj.a // [1, 2, 3, 4, 12]

//当对象多嵌套一层数组的时候,对数据进行修改,还是会相互影响,这种情况下只有深拷贝才能解决这种问题了。

深拷贝

方式一: JSON.parse(JSON.stringify(oldobj))

var obj = {
    a : 0,
    b : {c : 1}
}
var newobj = JSON.parse(JSON.stringify(obj));
 obj.a = 4;
 obj.b.c = 4;
 newobj = { a: 0, b: { c: 0}};  //互不干扰
然而这种使用JSON序列化的方法有使用限制
对象里有函数,函数无法被拷贝下来 对象原型链上的属性和方法无法被拷贝下来
var obj = { 
    a: 0, 
    b: function(){
        return this.a
    }
};
var newobj = JSON.parse(JSON.stringify(obj));
newobj // {a: 0}  -- 函数未被拷贝

方式二: 函数方式递归浅拷贝
- 先看函数方式的浅拷贝方法:

    function shallowCopy(source, target = {}) {
        var key;
        for (key in source) {
            if (source.hasOwnProperty(key)) {        // 意思就是__proto__上面的属性,我不拷贝
                target[key] = source[key];
            }
        }
        return target;
    }
    var obj = var obj = {a : 0,b : {c : 1}}

—明天再整理—

最新发布

CentOS专题

关于本站

5ibc.net旗下博客站精品博文小部分原创、大部分从互联网收集整理。尊重作者版权、传播精品博文,让更多编程爱好者知晓!

小提示

按 Ctrl+D 键,
把本文加入收藏夹