深拷贝和浅拷贝(实用版)

堆内存和栈内存

一、在js中,变量的储存对象主要有俩种方式:堆内存和栈内存;
二、 js中 数据类型有 值类型(基本数据类型){String number boolean null(null虽然作为一个object类型,但也是基本数据类型) undefined symbol}和引用数据类型{object array function}
三、 栈内存主要存储的是值类型(基本数据类型)以及堆内存中对象变量的指针;
四、堆内存主要存储引用数据类型;
五、栈内存是有序存储,容量小,系统分配率高;堆内存首先要分配存储区域,之后再把这个区域的位置(指针)存储到栈内存中;这就是为啥js在访问对象时,得根据地址(指针)去获取对象得值;

深拷贝和浅拷贝都是围绕堆内存和栈内存展开的,一个是处理堆内存中得值,一个是处理栈内存中的指针;

六、在栈内存中,基本数据类型都是相互独立的,互不影响;而在堆内存中,一个引用类型可以有多个指针,这些指针都指向同一个堆内存中的对象;某一个指针对这个引用类型的修改,其他指针指向的是被修改后的引用类型;

浅拷贝和深拷贝都是针对引用数据类型

七、浅拷贝只是复制指针,不复制引用数据类型本身;
八、深拷贝会复制引用数据类型本身,俩个对象一摸一样;新旧对象互不影响;

写一个浅拷贝方法
function lightcopy (zrobj) {
    var obj = {};
    //拷贝一层,深层次的对象就拷贝引用
    for(var i in zrobj){
        obj[i] = zrobj[i]
    }
    return obj;
}

var obj = {
    a:'1',
    b:{
        a:'2',
        fn(){
            console.log(this.a)
        }
    }
} 

var nowCopyObjOne = lightcopy(obj);
var nowCopyObjTwo = lightcopy(obj);
console.log(nowCopyObjOne.a)  //1
console.log(nowCopyObjOne.b.a)  //2
console.log(nowCopyObjOne.b.fn())  //2
console.log(nowCopyObjTwo.a)  //1
console.log(nowCopyObjTwo.b.a)  //2
console.log(nowCopyObjTwo.b.fn())  //2

nowCopyObjOne.b.a = '我被nowCopyObjOne修改啦'

console.log(nowCopyObjOne.a)  //1
console.log(nowCopyObjOne.b.a)  //我被nowCopyObjOne修改啦
console.log(nowCopyObjOne.b.fn())  //我被nowCopyObjOne修改啦
console.log(nowCopyObjTwo.a)  //1
console.log(nowCopyObjTwo.b.a)  //我被nowCopyObjOne修改啦
console.log(nowCopyObjTwo.b.fn())  //我被nowCopyObjOne修改啦
用ES6里面的Object.assign()《本身是用来合并多个对象》实现一个浅拷贝

Object.assign(target, …sources) target为目标对象。sources为任意多个源对象。

var a = {
    name:'睿睿'
};
var b = {
    age:'18'
};
var c = {
    gender:'男'
};
var d = {
    position:'程序猿'
};
Object.assign(b,c,d);
console.log(b)//{age: "18", gender: "男", position: "程序猿"}
//该方法会修改传入的第一个对象;所以要实现浅拷贝的话 第一个参数传{};
var dCopy = Object.assign({} , a , b , c , d)
//如果有重复的属性,会被右边的值覆盖,按照参数从左到右的顺序
//此时,由于Object.assign(b,c,d);  所以 b已经成为{age: "18", gender: "男", position: "程序猿"}
//所以:c 和 d 里面的属性会覆盖b中的属性
console.log(dCopy)//{name: "睿睿", age: "18", gender: "男", position: "程序猿"}
写一个深拷贝的方法(递归)
function deepClone(obj) {
    var deepObj = {};
    for(var key in obj) {
        //判断对象是否有下一级
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            //如果下一级也是对象
            if (typeof obj[key] === 'object') {
                //递归
                deepObj[key] = deepClone(obj[key]); 
            } else {
                deepObj[key] = obj[key];
            }
        }
    }
    return deepObj;
}
var obj = {
    a:'1',
    b:{
        a:'2',
        fn(){
            console.log(this.a)
        }
    }
} 
var deepCopyobjOne = deepClone(obj)
var deepCopyobjTwo = deepClone(obj)
console.log(deepCopyobjOne.a)  //1
console.log(deepCopyobjTwo.a)  //1

deepCopyobjOne.a='3';

console.log(deepCopyobjOne.a)  //3
console.log(deepCopyobjTwo.a)  //1
用JSON.parse和JSON.stringify实现深拷贝
var obj = {
    a:'1',
    b:{
        a:'2',
        fn(){
            console.log(this.a)
        }
    }
}
var deepObjJSONOne = JSON.parse(JSON.stringify(obj));
var deepObjJSONTwo = JSON.parse(JSON.stringify(obj));
console.log(deepObjJSONOne.a)  //1
console.log(deepObjJSONTwo.a)  //1

deepObjJSONOne.a='3';

console.log(deepObjJSONOne.a)  //3
console.log(deepObjJSONTwo.a)  //1

完!
(方法很实用,懂的比较浅,有问题多多指出;谢谢)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章