深浅拷贝
深浅拷贝是什么:
理解:简单来说,假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,如果B没变,那就是深拷贝;
先理解数据类型:
- 基本数据类型: undefined、boolean、number、string、null(可直接操作保存在变量中实际的值)
- 引用数据类型:js除了以上基本数据类型剩下是引用类型,即对象(属性和方法的集合)
基本数据类型
var name = 'nancy';
name.toUpperCase();//输出为NANCY
console.log(name);//输出为nancy
var person = 'nancy';
person.age = 20;
person,method = function(){...};
console.log(person.age);//undefind
console.log(person.method);//undefind
1.原始的name值是不会发生改变 2.基本类型不可添加属性和方法
基本数据类型的变量标识符和值是存放在栈内存中
赋值:
var a = 10;
var b = a;
a++;
console.log(a);//11
console.log(b);//10
基本数据类型两变量操作相互不影响
引用数据类型
var person = {};
person.age = 20;
person.sayName = function(){console.log(person.age)};
person.sayName();//20
delete person.age;
person.sayName();//undefind
引用类型的值可以动态改变
var person1 = {};
var person2 = {};
console.log(person1 == person2);//false
引用类型的值同时保存在栈内存和堆内存的对象,这里相等是比较两对象堆内存地址是否相同,显然这里不同
赋值:
var a = {};//a保存一个空对象实例
var b = a;//a,b都指向这空实例
a.age = 10;
console.log(a);//10
console.log(b);//10
保存在变量中的是对象在堆内存的地址,与基本数据类型数据赋值不同,这里的值实际是一个指向存储在堆内存的一个对象,两变量的指向都在同一个堆内存,因此改变一个值(堆内存中),另一变量的值也发生改变,深拷贝可解决此问题。
深拷贝优点:防止变量全局污染,解决方法如下:
//深、浅拷贝
//数组 slice() concat()
var arr3 = ['a','b','c'];
var arr4 = arr3;
arr4[1]= 100;
console.log(arr3);
var arr5 = arr3.slice(0); // var arr5 = arr3.concat();
arr5[1]= 99;
console.log(arr3);
//对象
var o6 = {
name:'abc',
age:18,
arr:[1,2],
o:{id:1},
action:function(){
}
};
var o7 = new Object(); //实际浅拷贝,虽然基本数据类型不会变,但是其引用对象还是会随之改变,深拷贝:所有的类型都不会随之改变
o7.name = o6.name;
o7.age = o6.age;
o7.o = o6.o;
o6.o.id = 'o6ID';
console.log(o7);
//Object.assign()
var ob1 = {a:1,b:2};
var ob2 = {x:1,y:2};
Object.assign(ob1,ob2);
console.log(ob1);//{a:1,b:2,x:1,y:2}
//合并的方法
function fun(o){
var obj = {};
Object.assign(obj,o); ////浅拷贝
return obj;
};
var ob1 = {a:1,b:2,sub:{id:1}};
var obj10 = fun(ob1);
ob1.a = 'aaaa';
obj10.sub.id = 100; //其方法还是会随之改变,仍然是浅拷贝
console.log(obj10);
console.log(ob1);
//深拷贝(挺好用的方法) 弊端:不支持function
var obj = {
name: 'sonia',
age: 18,
sub:{
id:1
},
action:function(){
console.log(this.age);
}
}
var obj2 = JSON.parse(JSON.stringify(obj));
obj.sub.id = 100;
console.log(obj2);
console.log(obj);
//2公共方法
var Animal={
name: "duobi",
skin: ["red", "green"],
child: {
xxx: "xxx"
},
say: function(){
console.log("I am ", this.name, " skin:", this.skin)
}
}
function deep(dest, obj){
var o = dest;
for (var key in obj) {
if (typeof obj[key] === 'object'){ //判断是不是对象(是不是数组或对象)
//(obj[key].constructor===Array)?[]:{}; //constructor判断类型是数组还是对象
//var o ={},arr = [];
//console.log(o.constructor == Object);console.log(arr.constructor == Array);
o[key] = (obj[key].constructor===Array)?[]:{};
deep(o[key], obj[key]);
} else {
o[key] = obj[key]
}
}
return o;
};
var x = deep({},Animal);
var y = deep({},Animal);
x.child.xxx = 'aaa';
console.log(x);
console.log(y);
}