前言
JavaScript的数据类型有两大类:
基本数据类型
引用类型
基本数据类型
string、number、null、undefined、boolean、symbol(ES6新增) 变量值存放在栈内存中,可直接访问和修改变量的值 基本数据类型不存在拷贝,好比如说你无法修改数值1的值
引用类型
Object Function RegExp Math Date 值为对象,存放在堆内存中 在栈内存中变量保存的是一个指针,指向对应在堆内存中的地址。 当访问引用类型的时候,要先从栈中取出该对象的地址指针,然后再从堆内存中取得所需的数据
浅拷贝
浅拷贝赋值引用地址,修改值会影响原始值(若属性的值未原始类型可能不会影响,依拷贝方法而定
- 直接赋值;
- 任何操作都会影响原数组;
JavaScript
let obj2 = obj1;- Object.assign;
- 拷贝属性值,假如属性值是一个对象的引用,那么也会指向那个引用;
JavaScript
let obj2 = Object.assign({},obj1);- Array.prototype.concat();
- 合并多个数组;
- 拷贝规则同Object.assign;
JavaScript
let arr2 = arr1.concat(...arr);- Array.prototype.slice();
- 提取数组;
- 参数(可选):startIndex,endIndex(与索引值一致);
- 拷贝规则同Object.assign;
JavaScript
let arr2 = arr1.slice(start,end);- 扩展运算符(...);
- 拷贝规则同Object.assign;
JavaScript
let obj2 = {obj1} or [...obj1];- lodash(_.clone());
- 拷贝规则同Object.assign;
JavaScript
let obj2 = _.clone(obj1);深拷贝
拷贝所有的属性,并且地址也与原来的不同,这样的话,你改变当前的属性也不会影响原来的
- JSON.parse(JSON.stringify());
但是该方法有以下几个问题:
会忽略 undefined
会忽略 symbol
不能序列化函数
不能解决循环引用的对象
不能正确的处理 new Date()
不能处理正则
JavaScript
function deepClone(obj) {
var _obj = JSON.stringify(obj)
var objClone = JSON.parse(_obj)
return objClone
}- 递归赋值;
JavaScript
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
//判断是否为自身属性
if(obj.hasOwnProperty(key)){
//判断ojb子元素是否为对象,如果是,递归复制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}- lodash(_.cloneDeep());
JavaScript
let obj2 = _.cloneDeep(obj1);