JS之深拷贝、浅拷贝

162 阅读3分钟

一、基本类型&&引用类型

1、ES中的变量类型分为两类:

基本类型:undefined,null,Boolean,String,Number

引用类型:Object,Array,Date,Function类型

2、不同类型的存储方式:

基本数据类型保存在栈内存,其中栈内存中分别存储着变量的标识符以及变量的值。


例如:var a = 'A'

上述代码在栈内存中是这样存储的:


而引用类型时保存在堆内存中的,栈内存存储的是变量的标识符以及对象在堆内存中的存储地址。当需要访问引用类型的值时,首先从栈中获得该对象的地址指针,然后再从对应的堆内存中取得所需的数据。


即:var a = { name: 'jack'};

在内存中是这样的:


3、不同类型的复制方式:

基本类型的复制:当你在复制基本类型的时候,相当于把值也一并复制给了新的变量。

var a = 1;
var b = a;
console.log(a === b);
var a = 2;
console.log(a);
console.log(b);


改变了a变量的值,并不会影响b的值。

引用类型的复制:当你在复制引用类型的时候,实际上只是复制了指向堆内存的地址,即原来的变量和复制的新变量指向了同一个东西。

var a = {name:"jack",age:20};
var b = a;
console.log(a === b);
a.age = 30;
console.log(a);
console.log(b);


内存中是这样的:

var a = {name:"jack",age:20};


var b = a;


a.age = 30;


深浅拷贝:

主要区别在于:复制的是引用(地址)还是复制的是实例。

浅拷贝:

1、Array中存在一些可以实现浅拷贝的方法:slice、concat...

2、一般的对象可以用Object的方法:assign

var obj = {name: '张三', dog: {name: '小黑'}};
var newObj = Object.assign({}, obj);
console.log(obj == newObj);

3、也可以使用ES6提供的语法(对象和数组都可以使用)

var obj = {name: '张三', dog: {name: '小黑'}};
var newObj = {...obj};



利用递归来实现深复制,对属性中所有引用类型的值

function deepClone(source) {
    if(!source && typeof source !== 'object') {
        throw new Error('error arguments', 'shallowClone')
    }
    var targetObj = Array.isArray(source) ? [] : {};
    for(var keys in source) {
        if(source.hasOwnProperty(keys)){
            if(source[keys] && typeof source[keys] === 'object'){
                targetObj[keys] = deepClone(source[keys]);
            } else {
                targetObj[keys] = source[keys];
            }
        }
    }
    return targetObj;
}


var a = {name: 'jack', age: 20};
var b = deepClone(a);
console.log(a === b)
a.age = 30;
console.log(a)
console.log(b)


1、Array的slice和concat方法并不是真正的深拷贝。

2、Jquery中的extend复制方法

可以用来扩展对象,这个方法可以传入一个参数:deep(true or false),表示是否执行深复制

(如果是深复制则会执行递归复制)

深拷贝:

var obj = {name: 'xixi', age: 20, company: { name: '腾讯', address: '深圳' } };
var obj_extend= $.extend(true, {}, obj); // extend方法,第一个参数为true,为深拷贝,为false,或者
没有为浅拷贝。
obj.company.name = 'ali';
obj.name = 'hei';

浅拷贝:

var obj = {name: 'xixi', age: 20, company: { name: '腾讯', address: '深圳' } };
var obj_extend= $.extend(false, {}, obj); // extend方法,第一个参数为true,为深拷贝,为false,或者
没有为浅拷贝。
obj.company.name = 'ali';
obj.name = 'hei';

JSON对象的parse和stringfy

JSON对象中的stringfy可以把一个js对象序列换为一个JSON字符串,parse可以把JSON字符串反序列化为一个js对象,这两个方法实现的是深拷贝。


var obj = {name:'xixi',age:20,company : { name : '腾讯', address : '深圳'} };
var obj_json = JSON.parse(JSON.stringify(obj));
console.log(obj === obj_json);
obj.company.name = "ali";
obj.name = "hei";
console.log(obj);
console.log(obj_json);