资讯专栏INFORMATION COLUMN

L - 浅拷贝与深拷贝的实现

Anshiii / 1491人阅读

摘要:也就是说,深拷贝与浅拷贝最主要的区别在引用类型的拷贝上。方法二递归拷贝深拷贝与浅拷贝相比不就是多拷贝几层的事嘛,这不就是递归常干的事嘛。

什么是浅拷贝和深拷贝 浅拷贝

浅拷贝:将一个对象自身的属性拷贝给另一个对象,如果源对象的属性是基本类型则直接进行值赋值,如果是引用类型则进行引用赋值,也就是说只进行一层赋值。

深拷贝

深拷贝:将一个对象自身的属性拷贝给另一个对象,如果源对象的属性是基本类型则直接进行值赋值,如果是引用类型则复制这个引用类型,使得目标对象拥有一个引用类型且和这个源属性一模一样,而非是一个指针。

也就是说,深拷贝与浅拷贝最主要的区别在引用类型的拷贝上。

注意,引用赋值不是浅拷贝!! 引用赋值仅仅只是赋值个指针,两个变量都指向同一内存区域,而浅拷贝是使得两个变量分别指向不同的内存区域

如果不懂,可以参考这里 一个小姐姐的博客

以上不是重点...

浅拷贝的实现 方法一 使用 for in 遍历
function shallowCopy(source){
    var target=source instanceof Array ? [] : {};
    for(var i in source){
        if(source.hasOwnProperty(i)){
            target[i]=source[i];
        }
    }
    return target;
}

// 测试
var obj={a:1,b:[1,2,3],c:function(){console.log("i am c")}}
var tar=shallowCopy(obj)
tar.c()         // "i am c"
obj.a=5
obj.a           // 5
tar.a           // 1
obj.b[0]=10
obj.b           // [10, 2, 3]
tar.b           // [10, 2, 3]

var arr=[1,2,[4,5,6]]
var newArr=shallowCopy(arr)
newArr          // [1, 2, [4,5,6]]
arr[0]=10
arr             // [10, 2, [4,5,6]]
newArr          // [1, 2, [4,5,6]]
arr[2][0]=10
arr             // [1, 2, [10,5,6]]
newArr          // [1, 2, [10,5,6]]
方法二 使用 Object.assign 或 slice、concat

Object.assign

var obj={a:1,b:[1,2,3],c:function(){console.log("i am c")}}
var tar={};
Object.assign(tar,obj);

当然这个方法只适合于对象类型,如果是数组可以使用slice和concat方法

Array.prototype.slice

var arr=[1,2,[3,4]];
var newArr=arr.slice(0);

Array.prototype.concat

var arr=[1,2,[3,4]];
var newArr=arr.concat();

测试同上(assign用对象测试、slice concat用数组测试),结合浅拷贝深拷贝的概念来理解效果更佳

深拷贝的实现 方法一 JSON黑科技
var obj={a:1,b:[1,2,3],c:function(){console.log("i am c")}}
var tar=JSON.parse(JSON.stringify(obj));

// 测试
obj.a=5
obj.a     // 5
tar.a     // 1
obj.b[0]=10
obj.b     // [10, 2, 3]
tar.b     // [1, 2, 3]
tar.c()   // Uncaught TypeError: tar.c is not a function

可以看到,无论是基本类型还是引用类型,两个对象的相同属性(属性名相同的属性)之间并没有关系了,但tar.c()报错了,我们打印看一下tar有什么console.log(tar) // {a: 1, b: Array(3)}可以看到c方法没了,这是和JSON的语法有关,JSON 并不支持函数类型的数据。这也就是这种方法的最大缺陷。

仔细一看,这并非黑科技,反而倒是有很大缺陷,不过很好用、效率高,只是在使用前需要稍加注意是否有函数类型的数据罢了。

方法二 递归拷贝

深拷贝与浅拷贝相比不就是多拷贝几层的事嘛,这不就是递归常干的事嘛。所以我们就想,在每次拷贝时都判断下,该属性是否是引用类型,如果是我们再递归调用拷贝方法,否则直接进行值赋值。

function deepCopy(obj,tar){
    var tar = tar || {};
    for(var i in obj){
        if(typeof obj[i] === "object"){
            if(obj[i].constructor === Array){
                tar[i] =[];
            }else{
                tar[i] = {};
            }
            deepCopy(obj[i],tar[i]);
          }
        else{
              tar[i] = obj[i];
          }
    }
    return tar;
}

// 使用
var obj={a:1,b:[1,2,3],c:function(){console.log("i am c")}};
var tar={};
deepCopy(obj,tar);
console.log(tar);

测试同上,你会惊喜的发现第一个方法中的函数bug没了

你看出来函数是怎样进行拷贝的了吗?很简单,typeof运算符的操作对象是一个函数时,得到的是 "function" 所以在循环里第一个if判断那为false 所以走else分支,在tar[i] = obj[i]这里,函数是进行引用赋值的,如果再造一个相同的函数不是不可以,只是不符合思想罢了,函数占用堆内存,如果可以共用当然是最好的选择。

当然这个方法还是有些许不足之处,不够已经很棒了

方法三 更严谨、更优雅的实现

这就需要去读一些好的源码了,比如Zepto、JQuery中extend方法的实现

现学现卖,如有不足请指出...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94062.html

相关文章

  • 拷贝与深拷贝区别

    摘要:浅拷贝与深拷贝一数据类型数据分为基本数据类型,和对象数据类型。浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。对于字符串数字及布尔值来说不是或者对象,会拷贝这些值到新的数组里。 浅拷贝与深拷贝 一、数据类型数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型。 基本数据类...

    jsyzchen 评论0 收藏0
  • JavaScript中拷贝与深拷贝

    摘要:所以,深拷贝是对对象以及对象的所有子对象进行拷贝实现方式就是递归调用浅拷贝对于深拷贝的对象,改变源对象不会对得到的对象有影响。 为什么会有浅拷贝与深拷贝什么是浅拷贝与深拷贝如何实现浅拷贝与深拷贝好了,问题出来了,那么下面就让我们带着这几个问题去探究一下吧! 如果文章中有出现纰漏、错误之处,还请看到的小伙伴多多指教,先行谢过 以下↓ 数据类型在开始了解 浅拷贝 与 深拷贝 之前,让我们先...

    546669204 评论0 收藏0
  • JavaScript中拷贝与深拷贝

    摘要:所以,深拷贝是对对象以及对象的所有子对象进行拷贝实现方式就是递归调用浅拷贝对于深拷贝的对象,改变源对象不会对得到的对象有影响。 上一篇 JavaScript中的继承 前言 文章开始之前,让我们先思考一下这几个问题: 为什么会有浅拷贝与深拷贝 什么是浅拷贝与深拷贝 如何实现浅拷贝与深拷贝 好了,问题出来了,那么下面就让我们带着这几个问题去探究一下吧! 如果文章中有出现纰漏、错误之处...

    AZmake 评论0 收藏0
  • 关于js拷贝与深拷贝

    摘要:原文地址浅拷贝和深拷贝只针对像这样的复杂对象的简单来说,浅拷贝只拷贝一层对象的属性,而深拷贝则递归拷贝了所有层级。浅拷贝通过来实现浅拷贝。 原文地址:http://www.silenceboy.com/201... 浅拷贝和深拷贝只针对像Object, Array这样的复杂对象的.简单来说,浅拷贝只拷贝一层对象的属性,而深拷贝则递归拷贝了所有层级。 浅拷贝 通过 Object.ass...

    summerpxy 评论0 收藏0
  • 20170606-拷贝与深拷贝

    摘要:什么是深拷贝,什么是浅拷贝中的浅拷贝与深拷贝是针对复杂数据类型引用类型的复制问题。 什么是深拷贝,什么是浅拷贝 JS中的浅拷贝与深拷贝是针对复杂数据类型(引用类型)的复制问题。 浅拷贝:浅拷贝是拷贝引用(拷贝地址),拷贝后两个变量指向的是同一块内存空间 深拷贝:会在内存中开辟一块新的内存空间,它不仅将原对象的各个属性逐个复制过去,而且将原对象各个属性所包含的内容也依次采用深复制的方法...

    Kerr1Gan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<