js程序中都是用对象结构来描述显示中一个事物,对象就是一组属性和方法的集合。
面向对象三大特点: 封装,继承,多态。
浅克隆是克隆 一层,深层次的对象级别的就克隆引用地址
深克隆是克隆 多层,每一级别的数据都会克隆出来
浅克隆就是克隆了一层,除了对象是克隆的引用类型地址,其他都是 按值传递,有自己的内存空间
点击进入查看按值传递
//------------------1------------------
function clone(initalObj) {
var obj = {
};
for ( var i in initalObj) {
obj[i] = initalObj[i];
}
return obj;
}
//------------------2------------------
var obj = {
a: "hello",
b:{
a: "world",
b: 21
},
c:["Bob", "Tom", "Jenny"]
};
//------------------3------------------
var cloneObj = clone(obj);
//------------------4------------------
console.log(cloneObj.a);
console.log(cloneObj.b);
console.log(cloneObj.c);
//------------------5------------------
cloneObj.a = "changed";
cloneObj.b.a = "changed";
cloneObj.b.b = 25;
cloneObj.c[3] = "Lilei";
//------------------6------------------
console.log(obj.a); //hello
console.log(obj.b); //{a:"changed",b:25}
console.log(obj.c); //['Bob','Tom','Jenny','Lilei']
通过以上代码可以看出来,obj.b
属性的属性值被 修改 cloneObj.b
值的时候修改 c
和 b
是同样的结果
事实上就是for in循环 克隆引用类型的时候,复制的都是引用地址
Object.assign(target, ...sources)
//参数:
// target:目标对象
// sources:任意多个源对象
//返回值:
// 目标对象会被返回
Object.assign()
方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
但是 Object.assign() 进行的是浅克隆,克隆的是对象的属性的引用,而不是对象本身。
var obj = {
a: "LiLei",
b: {
a: "LiXiaolei",
b: 21,
},
};
var cloneObj = Object.assign({
}, obj);
cloneObj.a = "changed";
cloneObj.b.a = "changed";
console.log(obj.a); //LiLei
console.log(obj.b.a); // "changed"
var obj2 = {
a: 1, b: 2, c: 3 };
var cloneObj2 = Object.assign({
}, obj2);
cloneObj2.b = 10;
console.log(obj2);
// { a: 1, b: 2, c: 3 }
console.log(cloneObj2);
// { a: 1, b: 10, c: 3 }
可以看到修改cloneObj2.b,原来obj2没有发生变化
定义函数在函数执行前判断类型:
是否为null、是就直接返回null;
是否为数组,是数组利用slice方法放到一个新数组返回;
在遍历的时候判断是否为引用类型,如果原对象中当前值是原始类型就可以直接赋值,否则当前属性不是原始类型的值,再次调用clone函数,继续复制当前属性值
var lilei={
sname:'lilei',
sage:11,
score:null,
firends:["jack","rose"],
address:{
prov:'北京',
city:'北京',
area:'海淀',
street:'成寿寺'
}
}
function clone(obj){
if(obj===null){
return null;
}
if({
}.toString.call(obj)==="[object Array]"){
var newArr=[];
newArr=obj.slice();
return newArr;
}
var newobj={
};
//遍历对象中的每个属性
for(var key in obj){
//如果原对象中当前值是原始类型就可以直接赋值
if(typeof obj[key]!=="object"){
//在新对象中添加和原对象中同名的属性
newobj[key]=obj[key];
//因为原始类型复制就是复制副本
}else{
//否则当前属性不是原始类型的值,再次调用clone函数,继续复制当前属性值
newobj[key]=clone(obj[key])
}
}
return newobj;
}
var lilei2=clone(lilei);
用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象
var obj1 = {
LiLei: {
age: 21 } };
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.LiLei.age = 25;
console.log(obj1);
// { LiLei: { age: 21 } }
console.log(obj2);
// { LiLei: { age: 25 } }
console.log(obj1 === obj2);
// false
console.log(obj1.body === obj2.body);
// false
这种方法在进行深克隆后不管原对象的构造函数是什么,现在的都会变成Object,所以不能对原型链上的属性和方法进行克隆。
这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。function没办法转成JSON,如果你的对象里有函数, 函数无法被拷贝下来。
Object.create(proto[, propertiesObject])
仅靠父对象就可以创建子对象的一个方法。
Object.create(proto[, propertiesObject])
//参数:
// proto:新创建对象的原型对象
// propertiesObject:可选。如果没有指定为 undefined,则是要添加到新创建对象的不可枚举(默认)属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()的第二个参数。
//返回值:
// 一个新对象,带着指定的原型对象和属性。
如下代码:
var obj = {
x: 1,
y: {
a: 1,
b: 0,
c: [1, 2, 3]
}
};
var obj2 = Object.create(obj);
console.log(obj2 == obj); //false
console.log(obj2);
在输出结果中可以看到,obj2自己并没有属性,属性全部都是继承于父对象