美文网首页
JavaScript 中的深浅拷贝

JavaScript 中的深浅拷贝

作者: liwuwuzhi | 来源:发表于2019-02-14 11:42 被阅读0次
let a = {
    age: 1
}
let b = a
a.age = 2
console.log(b.age) // 2

从上面的例子可以发现,如果给一个变量赋值一个对象,那么两者的值会是同一个引用,其中一方改变,另一方也会相应改变。

解决这个问题,可以引入浅拷贝:

浅拷贝

  1. 可以使用 Object.assign 来解决这个问题
let a = {
    age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
  1. 使用ES6展开运算符 ... 解决
let a = {
    age: 1
}
let b = {...a}
a.age = 2
console.log(b.age) // 1

通常浅拷贝能解决大部分的问题,但是当遇到,对象里面嵌套一个对象的时候,就需要用到深拷贝了

let a = {
    age: 1,
    name: {
        first: 'black'
    }
}
let = {...a}
a.name.first = 'guyue'
console.log(b.name.first) // guyue

这样说明浅拷贝并没有对嵌套的对象生效。此时需要深拷贝上场:

深拷贝

深拷贝最简单的实现办法就是使用 JSON.parse(JSON.stringify(object)) 来解决。

let a = {
    age: 1,
    name: {
        first: 'black'
    }
}
let b = JSON.parse(JSON.stringify(a))
a.name.first = 'guyue'
console.log(b.name.first) // black

但是当出现以下几种情况的时候,会出现问题:

let obj = {
    a: 1,
    b: {
        c: 2
    }
}
obj.c = obj.b
obj.d = obj.a
obj.b.c = obj.c
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)
// Uncaught TypeError: Converting circular structure to JSON

报错了,不能解决循环引用对象的问题。

let obj = {
       age: undefined,
    sex: function(){},
    name: 'black'
}
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj) // {name: "black"}

发现只拷贝了name ,而忽略了undefined和funcion。

所以,JSON.parse(JSON.stringify(obj))遇到这几种情况会出现问题:

  • 不会拷贝 undefined
  • 不能拷贝函数
  • 不能解决循环引用的对象
  • 只对自身的可枚举属性有效
  • 执行后对象的 construetor 属性指向 Object

所以采用下面的方式:

  1. 递归拷贝
function deepCopy(target){ 
let copyed_objs = [];//此数组解决了循环引用和相同引用的问题,它存放已经递归到的目标对象
    function _deepCopy(target){ 
        if((typeof target !== 'object')||!target){return target;}
        for(let i= 0 ;i<copyed_objs.length;i++){
            if(copyed_objs[i].target === target){
                return copyed_objs[i].copyTarget;
            }
        }
        let obj = {};
        if(Array.isArray(target)){
            obj = [];//处理target是数组的情况
        }
        copyed_objs.push({target:target,copyTarget:obj}) 
        Object.keys(target).forEach(key=>{ 
            if(obj[key]){ return;} 
            obj[key] = _deepCopy(target[key]);
        }); 
        return obj;
    } 
    return _deepCopy(target);
}



var a = {
    age: 1,
    name: {
        first: 'black'
    },
    age: undefined,
    sex: function(){},
}

var newObj = deepCopy(a)
newObj.name.first = 'guyue'

console.log(a) // {age: undefined, name: {first: "black"}, sex: ƒ}
console.log(newObj) // {age: undefined, name: {first: "guyue"}, sex: ƒ}
  1. lodash库 提供的_.defaultsDeep用来做深拷贝
var _ = require('lodash');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = _.defaultsDeep(obj1);
console.log(obj1.b.f === obj2.b.f);
// false

\color{#ccc}{以上内容来源:}
\color{#ccc}{作者:hu970804}
\color{#ccc}{链接:https://segmentfault.com/a/1190000016149265}
\color{#ccc}{來源:segmentfault}

\color{#aaa}{稍作修改}

相关文章

  • JavaScript中的深浅拷贝

    深浅拷贝 从上面的例子可以发现,如果给一个变量赋值一个对象,那么两者的值会是同一个引用,其中一方改变,另一方也会相...

  • JavaScript 中的深浅拷贝

    从上面的例子可以发现,如果给一个变量赋值一个对象,那么两者的值会是同一个引用,其中一方改变,另一方也会相应改变。 ...

  • javascript深浅拷贝

    Javascript有六种基本数据类型(也就是简单数据类型),它们分别是:Undefined,Null,Boole...

  • javascript深浅拷贝

    underscore 的源码中,有很多地方用到了 Array.prototype.slice() 方法,但是并没有...

  • JavaScript深浅拷贝

    简单讲呢,深浅拷贝,都是进行复制,那么区别主要在于复制出来的新对象和原来的对象是否会互相影响,改一个,另一个也会变...

  • Javascript深浅拷贝

    浅拷贝 1.基本数据类型 是存在栈中的,所以=赋值,都会创建一个新的空间,例如 变量b有自己独立的空间 2.对象数...

  • JavaScript深浅拷贝

    原文链接 http://blog.poetries.top/2018/12/21/js-deep-copy/ 关注...

  • Javascript深浅拷贝

    拷贝 复制与拷贝 复制:将一个对象a赋值给另一个变量b,这个只是存储了对象a的引用地址,是属于同一个对象 克隆:创...

  • JavaScript深浅拷贝

    一般来说,我们拷贝数据的时候:如果是基本数据类型,则会生成新的数据,修改拷贝后的数据不会影响原有数据。如果是对象/...

  • JavaScript 深浅拷贝

    深拷贝: 深拷贝即创建新的内存地址保存值(互不影响)浅拷贝: 共用同一内存地址,你改变我也跟着变 总结:slice...

网友评论

      本文标题:JavaScript 中的深浅拷贝

      本文链接:https://www.haomeiwen.com/subject/thaseqtx.html