一、赋值、浅拷贝与深拷贝的区别

二、深拷贝的方法
1.JSON转换
var targetObj = JSON.parse(JSON.stringify(copyObj))
let arr4 = JSON.parse(JSON.stringify(arr))
缺点:
(1)如果对象里有函数,函数无法被拷贝下来
(2)无法拷贝copyObj对象原型链上的属性和方法
(3)当数据的层次很深,会栈溢出
2.普通递归函数
function deepCopy( source ) {
if (!isObject(source)) return source; //如果不是对象的话直接返回
let target = Array.isArray( source ) ? [] : {} //数组兼容
for ( var k in source ) {
if (source.hasOwnProperty(k)) {
if ( typeof source[ k ] === 'object' ) {
target[ k ] = deepCopy( source[ k ] )
} else {
target[ k ] = source[ k ]
}
}
}
return target
}
function isObject(obj) {
return typeof obj === 'object' && obj !== null
}
缺点:
(1)无法保持引用
(2)当数据的层次很深,会栈溢出
3.防栈溢出函数
function cloneLoop(x) {
const root = {};
// 栈
const loopList = [
{
parent: root,
key: undefined,
data: x,
}
];
while(loopList.length) {
// 深度优先
const node = loopList.pop();
const parent = node.parent;
const key = node.key;
const data = node.data;
// 初始化赋值目标,key为undefined则拷贝到父元素,否则拷贝到子元素
let res = parent;
if (typeof key !== 'undefined') {
res = parent[key] = {};
}
for(let k in data) {
if (data.hasOwnProperty(k)) {
if (typeof data[k] === 'object') {
// 下一次循环
loopList.push({
parent: res,
key: k,
data: data[k],
});
} else {
res[k] = data[k];
}
}
}
}
return root;
}
优点:
(1)不会栈溢出
(2)支持很多层级的数据
function copyObject(orig) {
var copy = Object.create(Object.getPrototypeOf(orig));
copyOwnPropertiesFrom(copy, orig);
return copy;
}
function copyOwnPropertiesFrom(target, source) {
Object
.getOwnPropertyNames(source)
.forEach(function (propKey) {
var desc = Object.getOwnPropertyDescriptor(source, propKey);
Object.defineProperty(target, propKey, desc);
});
return target;
}
var obj = {
name: 'Jack',
age: '32',
job: 'developer'
};
var obj2 = copyObject(obj);
console.log(obj2);
obj.age = 39;
obj.name = 'Tom';
console.log(obj);
console.log(obj2);
3. 函数库lodash
该函数库也有提供 _.cloneDeep 用来做 Deep Copy。
var _ = require('lodash');
var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);
// false
浅拷贝的方法
slice()
concat()
Object.assign(target, ...sources)
{...obj} 和 [...arr]
循坏push
浅拷贝
const a = [1, {name: 'wang'}];
const b = [...a];
a[0] = 2;
a[1].name = 'li';
console.log(b)
b // [1, { name: 'li' } ]
const a = [1,2,3];
const b = a.concat();
const c = a.slice();
a[0] = 111111;
console.log(b);
console.log(c);
b // [1,2,3]
c // [1,2,3]
// 循环push
const a = { name: 'wang' };
const b = Object.assign({}, a);
a.name = 'li';
console.log(b);
b // { name: 'wang'}
var arr = [1,2,3,4,5]
var arr2 = copyArr(arr)
function copyArr(arr) {
let res = []
for (let i = 0; i < arr.length; i++) {
res.push(arr[i])
}
return res
}
下面是浅拷贝一个通用方法,实现思路:遍历对象,把属性和属性值都放在一个新的对象里
var shallowCopy = function (obj) {
// 只拷贝对象
if (typeof obj !== 'object') return;
// 根据obj的类型判断是新建一个数组还是一个对象
var newObj = obj instanceof Array ? [] : {};
// 遍历obj,并且判断是obj的属性才拷贝
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}
网友评论