目录
一、对象深拷贝的引入
对象属性们 Object.keys(obj1)返回数组装的obj1的所有成员名
var obj={name:"jack"},a="name";obj[a]可以取到"jack"Object.prototype.copy1=function () { //设计代码 让它有如下功能 } var obj={name:"karen",infos:[{img:"xx",count:20}]} var obj2=obj.copy1() obj2.infos[0].count=30 console.log(obj.infos[0].count)//30 var obj3=obj.copy1(true) obj3.infos[0].count=40 console.log(obj.infos[0].count)//30 console.log(obj3.infos[0].count)//40
二、对象的深拷贝的两种方法 ——笔试题常考——背
(笔试题中经常出现-跟垂直水平居中频率差不多)——(标准答案)
方法1. 最简单的方式,缺陷是原型链没有拷贝 函数和null不会拷贝
var copy1 = function (obj) { return JSON.parse(JSON.stringify(obj)); } var a = {a:function(){console.log('hello world')},b:{c:1},c:[1,2,3],d:"wanger",e:new Date(),f:null,g:undefined} var b = copy1(a)
方法2.利用自调用
var copy1 = function (obj) { if(obj === null) return null if(typeof obj !== 'object') return obj; if(obj.constructor===Date) return new Date(obj); if(obj.constructor === RegExp) return new RegExp(obj); var newObj = new obj.constructor (); //保持继承链 for (var key in obj) { if (obj.hasOwnProperty(key)) { //不遍历其原型链上的属性 var val = obj[key]; newObj[key] = typeof val === 'object' ? arguments.callee(val) : val; // 使用arguments.callee解除与函数名的耦合 } } return newObj; };
var oldObj = {
name: "karen",
age: "20",
arr1: [1, 2, 3],
techer: {
name: "jiang"
}
}
function deepClone(obj) {
if (typeof obj !== 'object' || obj == null) {
return obj
}
if (obj.constructor === Date) return new Date(obj);
if (obj.constructor === RegExp) return new RegExp(obj);
var result
if (obj instanceof Array) { //数组
result = []
} else { //对象
result = {}
}
for (let key in obj) {
if (obj.hasOwnProperty(key)) { //不遍历其原型链上的属性
result[key] = deepClone(obj[key])
}
}
return result
}
var newObj = deepClone(oldObj)
newObj.name = "jack"
newObj.techer.name = "li"
console.log(oldObj, newObj, newObj == oldObj)
三、对象的深拷贝的两种方法的讲解:
对象深拷贝的方法一: 如果内部没有引用数据或者时间正则null等等数据时,使用此方法
//想要结果是{name:"karen"} false,有以下两种方法 var obj={name:"karen"} // var obj2={} // obj2.name=obj.name var str=JSON.stringify(obj)//'{"name":"karen"}' var obj2=JSON.parse(str)//{name:"karen"} console.log(obj2,obj==obj2)//{name:"karen"} false
对象深拷贝的方法二:上面的那个方法不能使用,就使用自己封装的方法 (第3个)
1、深拷贝是两者一模一样,但是不相等,所以以下就不是深拷贝。因为下面的类型不一样。
var obj={x1:null,x2:new Date(),x3:"hello",son:{age:20}} var obj2=JSON.parse(JSON.stringify(obj)) //将obj对象转为字符串,再转为对象 console.log(obj2,obj) //两者的x2也不同,obj2是用引号括起来的,而obj没有引号,它是一个对象
2、dt 和dt2不一样 dt2是字符串 dt是对象
var dt=new Date() var dt2=JSON.parse(JSON.stringify(dt)) console.log(typeof dt2) //string
3、上面的 JSON.parse不能够实现深拷贝,下面就自己封装一个函数来实现深拷贝
注意:typeof(null) 是object
var obj = {
name: "karen",
its: [10, 20, 30]
} //[10,20,30,[90,100]]//null//"hello"//{x1:null,x2:new Date(),x3:"hello",son:{age:20}}
var obj2 = new Person()
function deepcopy(data) {
if (typeof (data) == "object") {
if (data.constructor == Date) { //时间格式
return new Date(data.getTime()) //返回一个新的时间对象
} else if (data == null) {
return null
} else if (data.constructor == RegExp) { //正则表达式
return new RegExp(data)
} else if (data.constructor == Array) {
var newArray = new Array()
for (var i = 0; i < data.length; i++) {
var temp = data[i]
newArray.push(arguments.callee(temp)) //函数的自调用
}
return newArray
} else {
var newobj = new data.constructor() //构造函数,既可以拷贝成员,也不会让原型链上的方法丢失
// Object.keys() //这个方法也可以遍历对象,和下面的 for in一样都可以实现遍历
for (var key in data) {
newobj[key] = arguments.callee(data[key]) //函数的自调用
}
return newobj
}
} else {
return data
}
}
var obj2 = deepcopy(obj)
// console.log(obj2,obj==obj2,obj[3]==obj2[3])
console.log(obj2, obj == obj2, obj.its == obj2.its)