java map 深度克隆_如何深度克隆一个对象

如何深度克隆一个对象在我们日常工作中经常会遇到需要去克隆一个对象比如多个地方用到的公共的图表基本参数的配置

相信很多人会想到用 Object.assign, JSON.stringify 和 JSON.parse 方法去克隆一个对象,这个可以明确告诉大家这些都是些不靠谱的浅度克隆。

我们先来试一下 Object.assign 在控制台执行下列操作

d5a8e4744f1913bde8d21be770679310.png

接下来我们看下 JSON.stringify 和 JSON.parse 克隆对象,同样在控制输入

00aaf82bff6964912812ed39c3ebff28.png

下面咋们来看一种稍微靠谱的一种方式。在本站搜的前几条中发现的。function isArray (arr) {

return Object.prototype.toString.call(arr) === '[object Array]';

}

// 深度克隆

function deepClone (obj) {

if(typeof obj !== "object" && typeof obj !== 'function') {

return obj; //原始类型直接返回

}

var o = isArray(obj) ? [] : {};

for(i in obj) {

if(obj.hasOwnProperty(i)){

o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];

}

}

return o;

}

看是靠谱是真是假我们来验证一把 还是在控制台输入

f109916b75f7f1ea27d39766447dfa5d.png

大家发现什么异常的了吗?

这个没有区分具体的对象,在此问下大家js的对象有哪些呢?相信一般人答不出来4个

[object Object], [object Array], [object Null], [object RegExp], [object Date], [object HTMLXXElement], [object Map],[object Set],... 等等一系列

检测类型使用 Object.prototype.toString.call(xxx) 和 typeof

我们分析下上面对象中哪些是引用类型需要特殊处理呢?相信大家都不陌生了。[object Object] 和 [object Array]

好!详细大家思路有了,咋们用递归来实现一把吧!const deepClone = function(obj) {

// 先检测是不是数组和Object

// let isMap = Object.prototype.toString.call(obj) === '[object Map];

// let isSet = Object.prototype.toString.call(obj) === '[object Set];

// let isArr = Object.prototype.toString.call(obj) === '[object Array]';

let isArr = Array.isArray(obj);

let isJson = Object.prototype.toString.call(obj) === '[object Object]';

if (isArr) {

// 克隆数组

let newObj = [];

for (let i = 0; i < obj.length; i++) {

newObj[i] = deepClone(obj[i]);

}

return newObj;

} else if (isJson) {

// 克隆Object

let newObj = {};

for (let i in obj) {

newObj[i] = deepClone(obj[i]);

}

return newObj;

}

// 不是引用类型直接返回

return obj;

};

Object.prototype.deepClone = function() {

return deepClone(this);

};咋们先不考虑Map Set Arguments [object XXArrayBuffer] 对象了原理都是一样

各种情况分析完了才说算是真克隆

我们在控制台看下注意先要把方法在控制台输进去,在调试

5a9ac63cf0a41f195aad6e74cf0a7607.png

是不是解决了? 在此并没有结束。 专注的伙伴们相信发现了对象中包含了个 deepClone 方法,具体细节我们在此就不多说了,我们给 Object 添加了个 Object.prototype.deepClone方法导致了每个对象都有了此方法。

原则上我们不允许在原型链上添加方法的,因为在循环中 for in, Object.entries, Object.values, Object.keys 等方法会出现自定义的方法。

相信熟悉 Object 文档的伙伴人已经知道解决方案了,

Object.defineProperty 这个方法给大家带来了福音 具体参考 Object 文档。我们使用一个enumerable (不可枚举)属性就可以解决了。

在原来基础上添加以下代码即可。Object.defineProperty(Object.prototype, 'deepClone', {enumerable: false});

在看控制台

7dffe7cd6b95dae9143ac074327213b4.png同样上面方法中也是无法克隆一个不可枚举的属性。

完整代码如下const deepClone = function(obj) {

// 先检测是不是数组和Object

// let isArr = Object.prototype.toString.call(obj) === '[object Array]';

let isArr = Array.isArray(obj);

let isJson = Object.prototype.toString.call(obj) === '[object Object]';

if (isArr) {

// 克隆数组

let newObj = [];

for (let i = 0; i < obj.length; i++) {

newObj[i] = deepClone(obj[i]);

}

return newObj;

} else if (isJson) {

// 克隆Object

let newObj = {};

for (let i in obj) {

newObj[i] = deepClone(obj[i]);

}

return newObj;

}

// 不是引用类型直接返回

return obj;

};

Object.prototype.deepClone = function() {

return deepClone(this);

};

Object.defineProperty(Object.prototype, 'deepClone', {enumerable: false});为了兼容低版本浏览器需要借助 babel-polyfill;

最后还是推荐lodash的cloneDeep方法。

好了,深度克隆介绍到此。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值