A New Start

JS的深复制和浅复制

一、问题暴露

    有一个全局的变量 a,是个 Json 对象,需求就是在很多方法中都会去使用它,但是不允许更改 a 的值。

    在使用的时候,仅仅是 var b = a;    

    但是发现每次改变 b 中的值得时候,a 中 的值也被改变了,原来 JS 也是对象的引用,专业一点的术语,这种复制叫做:浅复制

二、问题解决

    问题总该解决,研究发现,使用一种讨巧的方式,便可以实现:

    var b= JSON.parse(JSON.stringify(a));

    即,将 a 先反序列化成 js 对象,再序列化成 json 对象,完美解决。

三、再谈

    问题虽然解决了,但是碰到了总要稍微深入研究下。

    在 JS 的世界里,关于复制,有两种,称为浅复制和深复制(其实浅复制就是 Java 里面对象引用的时候引用了其内存地址,相同概念而已)。

    浅复制:复制引用,指向同一个对象实例。

    深复制:不是复制引用,而是重新分配了一块内存,并将原来的对象所有的属性都复制到该内存中,即是一个新的对象,和原来的对象相隔离。

    其实,关于深、浅复制的概念讨论,都是针对的“对象”,即 Object、Array 等,基本引用类型并不涉及,因为这些值本身就是存储在堆内存中的,不存在引用地址,如:null、undefined、string、number和boolean(JS 中 string 也在基本类型的范畴)。

    

四、再挖掘

    其实在深、浅复制的相关讨论中,还有一个概念叫“粒度”,就是说,深复制是指对象的递归复制,即如果对象内部包含对象,那么深复制的概念是递归完全复制。

    那么有一种状态是处于深复制和浅复制之间的,即“粒度”不够细的时候,意思就是,外层对象确实是有了新的内存分配,但是内层对象并没有完全隔离。

    比如 JQuery 中的 extend 方法,当给它的 deep传递参数 true 时,就进行了递归复制,即深复制,当传递 false 时,就是上面所提到的“中间态”,即仅仅是复制了外面的一层,但是其内部的对象,还是没有隔离开,相互之间还是会有影响。

    

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注