# 浅拷贝与深拷贝
# 数据类型
数据可分为基本数据类型和引用数据类型
- 栈:基本数据类型(Undefined, Null, Boolean, Number, String),直接存储在栈中的数据
- 堆:引用数据类型(对象、数组、函数),在栈中的存储指针,当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后,从堆中获得实体。
基本数据类型:占据的空间小,大小固定,频繁被使用的数据,所以存储在栈中 引用数据类型:占据的空间大,大小不固定
# 浅拷贝与深拷贝
浅拷贝与深拷贝只针对引用数据类型(array, object, function)
浅拷贝只复制指向的某个指针, 而不复制对象本身,新旧对象共享一个内存 深拷贝会创造一个一模一样的对象,新对象与原对象不共享内存,修改新对象不会改到原对象(指针指向不同堆地址)
# 赋值和浅拷贝的区别
- 当把一个对象赋值给一个新的对象时,赋的是栈中的地址,而不是堆中的数据。也就是两个对象指向同一个存储空间,即无论哪一个改变,存储空间的值会改变,两个对象是联动的
- 浅拷贝是按位拷贝对象,它会创建一个新的对象,这个对象有原对象属性值的精确拷贝,如果属性是基本类型,拷贝的就是基本类型的值,如果属性是存储地址(引用类型),则拷贝的是引用地址。因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝改造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源
var obj1={
"name": "hai",
"age": 18,
"language": [1, [2,3], 4]
}
var obj3 = shallowCopy(obj1);
obj3.name="lisa";
obj3.language[1]= 5;
function shallowCopy(src){
var dis={};
for(var key in src){
if(src.hasOwnProperty(key)){
dis[key] = src[key]
}
}
return dis;
}
console.log({obj1})
console.log({obj3})
// obj1 name 未变,language受obj3影响改变了
# 浅拷贝的实现方式
# 1 Object.assign()[当 object 只改变一层的时候是深拷贝,其他时候是浅拷贝]
let obj={
username: "koko"
};
let obj2 = Object.assign({}, obj);
obj2.username = "baba";
console.log(obj) // {username: "koko"}
let obj0 = {a: {username: "koko"}}
let obj02 = Object.assign({}, obj0);
obj02.a.username = "kaka";
console.log(obj0) // {a: {username: "kaka"}}
# 2 Array.prototype.concat()
let arr = [1,2,{name: "koba"}];
let arr2 = arr.concat();
arr2[2].name = "coco";
console.log(arr) // [1,2,{name: "coco"}];
# 3 Array.prototype.slice()
let arr = [1,2,{name: "koba"}];
let arr2 = arr.slice();
arr2[1] = 44;
console.log(arr) // [1,2,{name: "koba"}] 原数组不变
// arr2[2].name = "coco"; // 原数组会改变
// console.log(arr) // [1,2,{name: "coco"}];
# 深拷贝方法
# 1 JOSN.parse(JSON.stringify(obj)) 【不能成立函数】
json 变字符串,字符串变 json,新的对象产生,开辟一个新的栈
# 2 手写递归方法
// 定义检测数据类型的功能函数
function checkedType(target){
return Object.prototype.toString.call(target).slice(8, -1)
}
function clone(target){
let result, targetType = checkedType(target);
if(targetType === "Object"){
result={}
} else if(targetType === "Array"){
result = []
} else {
return target
}
for(let i in target){
let value = target[i]
if(checkedType(value) === "Object" || checkedType(value) === "Array"){
result[i] = clone(value)
} else{
result[i] = value;
}
}
return result;
}
# 3 lodash 函数库
var _ = require('lodash');
var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f); // false