对象深度拷贝

阅读次数:33 次  |  发布时间:2020-08-03T08:26:50Z 

//JSON.stringify深度克隆对象;
//1.无法对函数 、RegExp等特殊对象的克隆;
//2.会抛弃对象的constructor,所有的构造函数会指向Object;
//3.对象有循环引用,会报错
const objDeepClone = obj = > {
	return clone(obj)
}

const isType = (obj, type) = > {
	if (typeof obj !== 'object') return false;
	// 判断数据类型的经典方法:
	const typeString = Object.prototype.toString.call(obj);
	let flag;
	switch (type) {
	case 'Array':
		flag = typeString === '[object Array]';
		break;
	case 'Date':
		flag = typeString === '[object Date]';
		break;
	case 'RegExp':
		flag = typeString === '[object RegExp]';
		break;
	default:
		flag = false;
	}
	return flag;
};

/**
 * deep clone
 * @param  {[type]} parent object 需要进行克隆的对象
 * @return {[type]}        深克隆后的对象
 */
const clone = parent = > {
	// 维护两个储存循环引用的数组
	const parents = []
	const children = []

	const _clone = parent = > {
		if (parent === null) return null
		if (typeof parent !== 'object') return parent

		let child, proto

		if (isType(parent, 'Array')) {
			// 对数组做特殊处理
			child = []
		} else if (isType(parent, 'RegExp')) {
			// 对正则对象做特殊处理
			child = new RegExp(parent.source, getRegExp(parent))
			if (parent.lastIndex) child.lastIndex = parent.lastIndex
		} else if (isType(parent, 'Date')) {
			// 对Date对象做特殊处理
			child = new Date(parent.getTime())
		} else {
			// 处理对象原型
			proto = Object.getPrototypeOf(parent)
			// 利用Object.create切断原型链
			child = Object.create(proto)
		}

		// 处理循环引用
		const index = parents.indexOf(parent)

		if (index !== -1) {
			// 如果父数组存在本对象,说明之前已经被引用过,直接返回此对象
			return children[index]
		}
		parents.push(parent)
		children.push(child)

		for (const i in parent) {
			// 递归
			child[i] = _clone(parent[i])
		}

		return child
	}
	return _clone(parent)
}

console.log(objDeepClone({
	name: '张三',
	age: 23,
	obj: {
		name: '李四',
		age: 46
	},
	arr: [1, 2, 3]
})) // { name: '张三', age: 23, obj: { name: '李四', age: 46 }, arr:[ 1, 2, 3 ] }

最近发布的代码:

JavaScript生成随机码 JavaScript 程序  |  32次阅读  | 发布于:2020-08-11T07:07:50Z
switch 简写 JavaScript 程序  |  30次阅读  | 发布于:2020-08-03T23:01:51Z
短路运算 - & JavaScript 程序  |  34次阅读  | 发布于:2020-08-03T23:01:34Z
短路运算 - ||(或) JavaScript 程序  |  34次阅读  | 发布于:2020-08-03T23:01:21Z
使用Boolean过滤数组假值 JavaScript 程序  |  30次阅读  | 发布于:2020-08-03T23:01:06Z
JavaScript动态判断数据类型 JavaScript 程序  |  32次阅读  | 发布于:2020-08-03T23:00:51Z
JavaScript奇偶数判断 JavaScript 程序  |  32次阅读  | 发布于:2020-08-03T23:00:09Z
JavaScript数字取整 JavaScript 程序  |  35次阅读  | 发布于:2020-08-03T22:59:49Z
双位运算符 JavaScript 程序  |  33次阅读  | 发布于:2020-08-03T22:59:19Z
判断小数是否相等 JavaScript 程序  |  37次阅读  | 发布于:2020-08-03T22:58:36Z
字符串转数字 - 使用 + 操作符 JavaScript 程序  |  31次阅读  | 发布于:2020-08-03T22:58:03Z
字符串转数字 - 用*1来转化为数字,实际上是调用.valueOf方法 JavaScript 程序  |  33次阅读  | 发布于:2020-08-03T22:57:17Z
Number的数字千分位格式化 JavaScript 程序  |  39次阅读  | 发布于:2020-08-03T22:56:51Z
转化为字符串 JavaScript 程序  |  33次阅读  | 发布于:2020-08-03T22:55:24Z
url参数反序列化 JavaScript 程序  |  38次阅读  | 发布于:2020-08-03T22:55:12Z
url参数序列化 JavaScript 程序  |  35次阅读  | 发布于:2020-08-03T22:54:44Z
字符串翻转 JavaScript 程序  |  33次阅读  | 发布于:2020-08-03T22:53:00Z
函数异步执行 - Async/Await JavaScript 程序  |  41次阅读  | 发布于:2020-08-03T22:52:40Z
函数异步执行 - Generator JavaScript 程序  |  36次阅读  | 发布于:2020-08-03T22:52:14Z
函数异步执行 - Promise JavaScript 程序  |  34次阅读  | 发布于:2020-08-03T22:51:44Z
函数自执行 JavaScript 程序  |  30次阅读  | 发布于:2020-08-03T22:50:53Z
函数隐式返回值 JavaScript 程序  |  36次阅读  | 发布于:2020-08-03T22:50:06Z
JavaScript对象转化为字符串 JavaScript 程序  |  34次阅读  | 发布于:2020-08-03T22:49:15Z
对象是否相等 JavaScript 程序  |  29次阅读  | 发布于:2020-08-03T08:28:27Z
对象深度拷贝 JavaScript 程序  |  33次阅读  | 发布于:2020-08-03T08:26:50Z
拦截对象 JavaScript 程序  |  31次阅读  | 发布于:2020-08-03T08:26:23Z
拦截对象 JavaScript 程序  |  30次阅读  | 发布于:2020-08-03T08:25:50Z
解构对象属性默认值 JavaScript 程序  |  30次阅读  | 发布于:2020-08-03T08:25:31Z
解构对象属性别名 JavaScript 程序  |  33次阅读  | 发布于:2020-08-03T08:25:21Z
对象嵌套属性解构 JavaScript 程序  |  32次阅读  | 发布于:2020-08-03T08:25:11Z

最多阅读的代码

 getAttribute和getAttributeNode JavaScript 程序  |  1542次阅读
 一种很帅的JS代码书写方式 JavaScript 程序  |  1269次阅读
 Chrome 滚动条冻结现象 JavaScript 程序  |  1244次阅读
 Web弹出类似Android的Toast的信息提示 JavaScript 程序  |  1200次阅读
 通过jQuery发送ajax请求 JavaScript 程序  |  1108次阅读
 js为object动态添加属性 JavaScript 程序  |  1045次阅读
 [小Tip]Webkit下设置hash的一个坑 JavaScript 程序  |  953次阅读
 AMD 的 CommonJS wrapping JavaScript 程序  |  896次阅读
 用Opera Mobile调试手机版网页 JavaScript 程序  |  750次阅读
 在自己的网页中嵌入百度搜索框 JavaScript 程序  |  623次阅读
 Javascript八进制转义字符转中文 JavaScript 程序  |  548次阅读
 jQuery获取Select选择的Text和Value JavaScript 程序  |  528次阅读
 处理字符串的常见操作之截取:substring JavaScript 程序  |  370次阅读
 JavaScript跨平台(兼容各个平台)事件 JavaScript 程序  |  366次阅读
 用JavaScript添加style节点 JavaScript 程序  |  361次阅读
 把一个Array追加到另一个Array上 JavaScript 程序  |  352次阅读
 JavaScript字符与ASCII码间的转换 JavaScript 程序  |  351次阅读
 如何跳出双重循环 JavaScript 程序  |  345次阅读
 jquery判断两次点击对象是否是同一对象 JavaScript 程序  |  344次阅读
 Array迭代器 JavaScript 程序  |  341次阅读
 用jQuery把页面上的一个tag换成另一个tag JavaScript 程序  |  340次阅读
 合并两个Array并去掉重复项 JavaScript 程序  |  329次阅读
 JavaScript删除数组中的项 delete vs splice JavaScript 程序  |  327次阅读
 JavaScript中克隆对象 JavaScript 程序  |  315次阅读
 JavaScript判断浏览器类型及主版本 JavaScript 程序  |  312次阅读
 JavaScript中base64编码 JavaScript 程序  |  311次阅读
 检查一个object是否是jQuery object JavaScript 程序  |  307次阅读
 判断一个对象是否为数组 JavaScript 程序  |  296次阅读
 通过原型继承创建一个新对象 JavaScript 程序  |  296次阅读
 检查一个数是否为整数或浮点数 JavaScript 程序  |  276次阅读