前言:
主要是对自己看的一些知识总结和记录,地址:https://juejin.im/post/5abb55ee6fb9a028e33b7e0a
浅拷贝:
浅拷贝是对象只会克隆最外部的一层,更深层依然指向同一块堆内存
function shallowClone(obj) {
var res = {};
for(var i in obj) {
res[i] = obj[i];
}
return res;
}
var oldObj = {
a: 1,
b: 2,
c: { h: 3 }
}
var newObj = shallowClone(oldObj);
console.log(newObj.c.h,oldObj.c.h);
console.log(newObj.a === oldObj.a);
newObj.c.h = 11;
console.log(newObj.c.h,oldObj.c.h);
深克隆:
第一种方式:JSON.stringify(),和JSON.parse()
var newObj = JSON.parse(JSON.stringify(oldObj));
这种方式存在的问题:
1.无法实现对函数,regexp等对象克隆
2.会抛弃对象的cosntructor,所有的构造函数会指向object
3.对象有循环引用会报错
第二种方式:编写一个函数
主要思路判断每种类型的对象去进行不同的处理
function Clone() {
this.oldObj = [];
this.newObj = [];
}
Clone.prototype.getRegExp = function (re) {
var flags = '';
if (re.global) flags += 'g'; // 判断是否有g修饰符(全局查找修饰符)
if (re.ignoreCase) flags += 'i'; // 判断是否有i修饰符(大小写不敏感修饰符)
if (re.multiline) flags += 'm'; // 判断是否有m修饰符(多行匹配)
return flags;
}
Clone.prototype.isType = function (obj,type) {
if(typeof obj !== 'object') return false; //不等于对象返回
var typeString = Object.prototype.toString.call(obj); //获取类型
var flag;
switch(type) {
case 'Array':
flag = typeString === '[object Array]';
case 'Date':
flag = typeString === '[object Date]';
break;
case 'RegExp':
flag = typeString === '[object RegExp]';
break;
default:
flag = false;
}
return flag;
}
Clone.prototype.deepClone = function (obj) {
if(obj === null) return null; //等于空返回
if(typeof obj !== 'object') return obj; //不等于对象返回
var child,proto;
if(this.isType(obj,'Array')){ //判断是否是数组
child = []; //新建一个数组
}else if(this.isType(obj,'RegExp')){ //判断是否是正则
child = new RegExp(obj.source, this.getRegExp(obj)); //新建一个正则对象,并赋予要复制的参数
}else if(this.isType(obj,'Date')){ //判断是否是date对象
child = new Date(obj.getTime()); //新建一个Date对象,并赋予要复制的时间
}else{
child = Object.create(obj); //创建一个拥有指定原型和若干个指定属性的对象。
}
var index = this.oldObj.indexOf(obj);
if(index != -1){
// 如果存在本对象,说明之前已经被引用过,直接返回此对象
return this.newObj[index];
}
this.oldObj.push(obj);
this.newObj.push(child);
for(var i in obj){
child[i] = this.deepClone(obj[i]);
}
return child;
}
测试:
var clone = new Clone;
function deepClone(obj) {
return clone.deepClone(obj);
}
function person(pname) {
this.name = pname;
}
var Messi = new person('Messi');
function say() {
console.log('hi');
}
var oldObj = {
a: say,
c: new RegExp('/ain/', 'ig'),
d: Messi,
};
oldObj.b = oldObj;
var newObj = deepClone(oldObj);
console.log(newObj.a, oldObj.a);
console.log(newObj.b, oldObj.b);
console.log(newObj.c, oldObj.c);
console.log(newObj.d.constructor, oldObj.d.constructor);