一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第18天,点击查看活动详情。
大家好,我是大帅子,今天给大家讲一下深浅拷贝,下面我们直接开始吧
浅拷贝
let obj = {
name : "张三",
age : 18
}
目标: 把obj这个对象复制一份, 得到 obj1
,保证 obj
跟 obj1
一模一样,但是又是完全独立的两个对象
做法: 就是把obj里面的属性全都拿出来 ,做循环,把属性赋值跟obj1,
示例代码 :
- 传统做法
function clone(obj) {
let obj1 = {}
for(let key in obj){
obj1[key]=obj[key]
}
}
- 我们
es6
出来的新语法有个扩展运算法
也就是所谓的...
,解决了繁琐的代码
let obj = {name : 'zs',age:18}
obj1 = {...obj}
这里我们实现的就是浅拷贝哦
深拷贝 (deep clone) 在浅拷贝的基础上,对当前要复制的内容进行判断:如果仍是一个对象,则再次调用拷贝函数。
var obj = { name: '小王', hobby:['reading','running'] }
// 对于当前要拷贝的内容,如果还是一个对象,则要递归调用,而不是直接赋值
function deepCopy(obj){
// 定义一个空的对象或者是数组
// 如果当前要复制的是数组就用一个空数组,或者用一个空对象。
// var tempObj = Array.isArray(obj) ? [] : {}
var tempObj = {}
if( Array.isArray(obj) ) {
tempObj = []
}
// var tempObj = {}
// .... 操作
for(var key in obj) {
var t = obj[key]
// 当要拷贝的内容还是一个对象或者是数组
if(Array.isArray(t) || typeof t === "object") {
tempObj[key] = deepCopy(obj[key])
}
else // 当要拷贝的内容只是一个基本类型的数据
{
tempObj[key] = t
}
}
return tempObj
}
var obj1 = deepCopy(obj);
// 验证:
// 给 obj1.hobby.添一个信息,不会影响obj.hobby.
obj1.hobby === obj.hobby; // false
上面的代码可以简化如下:
function isObj(obj) {
return (typeof obj === 'object' || typeof obj === 'function') && obj !== null
}
function deepCopy(obj) {
var tempObj = Array.isArray(obj) ? [] : {}
for(var key in obj) {
tempObj[key] = isObj(obj[key]) ? deepCopy(obj[key]) : obj[key]
}
return tempObj
}
上面的代码在没有遇到循环引用之前都是正常工作的。下面将来介绍循环引用 。
循环引用 下面来看一个循环引用的例子:
注意下面第5行代码,obj.a还是指向了obj,这里就构成了一个环。
var obj = {
name: '小王',
hobby: ['reading', 'running'],
}
obj.a = obj; // 手动加上循环引用
function isObj(obj) {
return (typeof obj === 'object' || typeof obj === 'function') && obj !== null
}
function deepCopy(obj) {
var tempObj = Array.isArray(obj) ? [] : {}
for (var key in obj) {
tempObj[key] = isObj(obj[key]) ? deepCopy(obj[key]) : obj[key]
}
return tempObj
}
var obj1 = deepCopy(obj)
console.log(obj);
console.log(obj1);
console.log(obj1.hobby === obj.hobby);
导致的后果就是
Object.assign()拷贝
当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝。
通过jQuery的extend方法实现深拷贝
let $ = require('jquery');
let obj1 = {
a: 1,
b: {
f: {
g: 1
}
},
c: [1, 2, 3]
};
let obj2 = $.extend(true, {}, obj1);
lodash.cloneDeep()实现深拷贝
let _ = require('lodash');
let obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
let obj2 = _.cloneDeep(obj1);
使用递归的方式实现深拷贝
function _deepClone(source) {
let target;
if (typeof source === 'object') {
target = Array.isArray(source) ? [] : {}
for (let key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] !== 'object') {
target[key] = source[key]
} else {
target[key] = _deepClone(source[key])
}
}
}
} else {
target = source
}
return target
}
JSON.stringify 和 JSON.parse
用 JSON.stringify 把对象转换成字符串,再用 JSON.parse 把字符串转换成新的对象。
可以转成 JSON 格式的对象才能使用这种方法,如果对象中包含 function 或 RegExp 这些就不能用这种方法了。
//通过js的内置对象JSON来进行数组对象的深拷贝
function deepClone(obj) {
let _obj = JSON.stringify(obj);
let objClone = JSON.parse(_obj);
return objClone;
}
好了,这边已经给大家介绍到这里,以上是我自己的理解,希望可以帮到大家, 欢迎留言我这边一定会第一时间给大家解答,喜欢的可以点赞收藏,
🐣---->🦅 还需努力!大家一起进步!!!