js数组的拷贝赋值复制二三事总结

今天在看react-native性能优化的时候,看到如何避免shouldComponentUpdate的异常数据时,脑内一阵风暴,从而牵连出一连串的问题,于是有了这一篇关于js数组的复制(深浅拷贝)与赋值等为何能产生异常数据的文章。

有什么问题欢迎指正

 

现在进入正题:

首先异常数据的产生在于我们在复制赋值时,会有或没有改变到本身的值。

 

一、深拷贝与浅拷贝

1.浅拷贝

JavaScript存储对象都是存地址的,所以浅复制会导致 a 和 b 指向同一块内存地址

数组的赋值其实相当于给了索引,改变其中一个变量其他引用都会改变

 

var a = [1,2,3];
var b = a;
b[0] = 4;
//a为4 2 3
//b为4 2 3

 

根据上面存储对象的问题,这里就可以解决另一个问题:

    原始参数(比如一个具体的数字)被作为值传递给函数,如果被调用函数改变了这个参数的值,这样的改变不会影响到全局或调用函数。

    你传递一个对象(在js里数组不是简单数据类型,而是对象)到一个函数,如果在函数里面改变了这个参数的内容,在外部这个变化是可见的。

 

看下面三个深拷贝还是浅拷贝

(1)Object.assgin

(2)slice 函数

(3)concat 函数

 

三个函数的原理都是返回数组的一个副本(相当于另外开辟内存空间),所以并不会改变基础类型的值,看似深拷贝,但是引用类型还是用的索引,即还会发生变化

 

Object.assgin,例子如下:

var a = {
	a1:{
		aa1:'11',
		aa2:'22'
	}
}
var b = Object.assgin({},a);
var c = Object.assgin({},a);
b.a1.aa1 = 33;
/*
b:{
	a1:{
		aa1:'33',
		aa2:'22'
	}
}
c:{
	a1:{
		aa1:'33',
		aa2:'22'
	}
}
*/

 

slice 例子如下:

var a = [1,[2,3],4]
var b = a.slice(1)

//b = [[2,3],4]

a[1][0] = 5
a[2] = 6

//a = [1,[5,3],6]
//b = [[5,3],6]

concat 与之相似

 

2.深拷贝

那如何进行深拷贝呢

(1)用递归函数,遍历引用对象至基础类型然后进行复制

function deepClone(obj) {
    var newObj = obj instanceof Array ? [] : {};
    //obj属于基本数据类型,直接返回obj
    if(typeof obj !== 'object') {
        return obj;
    } else {
    //obj属于数组或对象,遍历它们
        for(var i in obj) {
            newObj[i] = typeof obj[i] === 'object' ? deepClone(obj[i]):obj[i]; 
        }
    }
    return newObj;
}

 

(2)JSON对象的parse和stringify

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

只能正确处理的只有Number、String、Boolean,Aarry,扁平对象,即那些能够被json直接表示的数据结构

所以缺点是:

1、会忽略 undefined

2、会忽略 symbol

3、不能序列化函数

4、不能解决循环引用的对象

5、不能正确处理new Date()

6、不能处理正则

 

(3)JQ的extend方法,实质是就封装一个递归函数

$.extend(true, object1, object2);

 

 

你可能感兴趣的:(Javascript)