-
-
Notifications
You must be signed in to change notification settings - Fork 230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
深拷贝 #58
Comments
你map的value存的是true? |
正则... |
let obj = {
a: 1,
b: 2,
c: {
c: 1,
d: 2
}
}
// 方法一
let obj1 = JSON.parse(JSON.stringify(obj))
// 测试用例
// console.log(obj1);
// obj1.b = 22
// obj1.c.c = 11
// console.log(obj);
// 方法二
function deepClone(obj) {
let objClone = Array.isArray(obj) ? [] : {}
for(let key of Object.keys(obj)) {
objClone[key] = (typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key])
}
return objClone
}
console.log(deepClone(obj)) |
export function objDeepCopy(source) {
if (typeof source === "object") {
var sourceCopy = source instanceof Array ? [] : {}
for (var item in source) {
if (!source[item]) {
sourceCopy[item] = source[item]
} else {
sourceCopy[item] =
typeof source[item] === "object"
? objDeepCopy(source[item])
: source[item]
}
}
return sourceCopy
}
return source
} |
深拷贝:只是针对Object 和 Array这样的引用数据类型的。 浅拷贝的实现方式:当对象object 只有一层的时候,是深拷贝
深拷贝的实现方式:1. json.stringfiy 和 parselet a = {
name: 'ss',
}
let b = JSON.parse(JSON.stringify(a)); 缺点:
2. 手写递归深拷贝const deepcolne = (target, map = new WeekMap()) =>{
// 基本类型直接返回
if(typeof target !== 'object' || target === null) return target;
// 函数 正则 日期 ES6新对象, 执行构造
const constructor = target.constructor;
if (/^(Function|RegExp|Date|Map|Set)$/i.test(constructor.name)) return new constructor(target);
// map 标记每一个出现过的属性,避免循环引用
if(map.get(target)) return map.get(target);
map.set(target, true);
const cloneTarget = Array.isArray(target) ? [] : {};
for(const prop in target){
cloneTarget[prop] = deepclone(target[prop], map);
}
return cloneTarget;
} 3. loadash函数库let _ = require('loadash');
_.cloneDeep(); |
function deepClone(origin) {
const map = new WeakMap(); // 解决循环引用
const clone = (obj) => {
if (typeof obj !== 'object') {
return obj;
}
if (map.has(obj)) {
return map.get(obj);
}
let newObj = Array.isArray(obj) ? [] : {};
map.set(obj, newObj);
Object.keys(obj).forEach(key => {
newObj[key] = clone(obj[key]);
})
return newObj;
}
return clone(origin);
}
const newObj = structuredClone(obj); // 不能拷贝函数 |
// 判断数据类型
const isType = (val) => {
return (type) => Object.prototype.toString.call(val) === `[object ${type}]`
}
function deepMerge(target) {
const ret = Array.isArray(target) ? [] : {};
for (let key in target) {
if (target.hasOwnProperty(key)) {
if (isType(target[key])('Object')) {
// 判断对象的值是不是对象,如果是对象则进一步递归
ret[key] = deepMerge(target[key])
} else if (isType(target[key])('Array')) {
// 如果是数组则进一步进行遍历数组,用一个新数组[]去添加值
ret[key] = [].concat([...deepMerge(target[key])]);
} else {
ret[key] = target[key]; // 如果是基础数据类型,则直接赋值
}
}
}
return ret;
} |
解决循环引用,和拷贝不可枚举对象!! /**
* 深拷贝会拷贝不可枚举属性,浅拷贝不会
* @param {*} target
* @param {*} map 避免循环引用
*/
function _deepClone(target, map = new Map()) {
if(typeof target !== "object" || target === null) return target;
if(map.get(target)) return map.get(target); // 避免循环引用
// 除了{}和[],new target.constructor(target)都可以重新开辟内存
if(/^(Function|RegExp|Date|Set|Map)$/.test(target.constructor.name)) {
const res = new target.constructor(target);
map.set(target, res);
return res;
}
const cloneTarget = Array.isArray(target) ? [] : {}
Object.getOwnPropertySymbols(target).forEach(item => {
cloneTarget[item] = _deepClone(target[item], map);
map.set(target, cloneTarget[item]);
})
Object.getOwnPropertyNames(target).forEach(item => {
if(!target.propertyIsEnumerable(item)) {
Object.defineProperty(target, item, Object.getOwnPropertyDescriptor(target,item));
} else {
cloneTarget[item] = _deepClone(target[item], map);
map.set(target, cloneTarget[item]);
}
})
// Object.propertyIsEnumerable() 判断是否是不可枚举的属性值
return cloneTarget;
}
const arr = [1,2,3]
const data = {
o: arr,
// a: function() {},
b: {
a: arr
}
}
Object.defineProperty(data, 'c', { enumerable: false, value: 2 }) // 默认设置为不可读不可写
const res = _deepClone(data)
console.log(res)
console.log(arr == res.b.a) |
function deepCopy(obj) {
// 确定需要复制的对象类型
const type = Object.prototype.toString.call(obj).slice(8, -1);
// 根据类型进行处理
switch (type) {
case "Object":
const newObj = {};
for (let key in obj) {
newObj[key] = deepCopy(obj[key]);
}
return newObj;
case "Array":
const newArr = [];
for (let i = 0; i < obj.length; i++) {
newArr.push(deepCopy(obj[i]));
}
return newArr;
case "Date":
return new Date(obj.getTime());
case "RegExp":
return new RegExp(obj);
default:
return obj;
}
} |
if(map.get(target)) return map.get(target); |
function isObject(val) {
return typeof val === "object" && val !== null;
}
// 难点如下:
// 1)注意收集 Symbol 属性
// 2) 注意可能会有循环引用,所以使用 map 记录,返回一个循环的指向即可,避免持续运行爆栈
// 3)注意一些特殊对象,Function,RegExp,Date,Map,Set这些,需要去构造新的实例
// 3)区分数组还是对象, 数组会有 ['0', '1', '2', 'length'] 这些属性,构造新的对象
function deepClone(obj, hash = new WeakMap()) {
if (!isObject(obj)) return obj; // 不是对象不拷贝直接返回
if (hash.has(obj)) { // 如果哈希表中有这个对象的记录,取出并返回
return hash.get(obj);
}
// 函数 正则 日期 ES6新对象,执行构造题,返回新的对象
const constructor = obj.constructor;
if (/^(Function|RegExp|Date|Map|Set)$/i.test(constructor.name)) return new constructor(obj);
let target = Array.isArray(obj) ? [] : {}; // 拷贝对象还是数组,创建新的内存地址
hash.set(obj, target); // hash 表记录对象
Reflect.ownKeys(obj).forEach((item) => {
if (isObject(obj[item])) { // 子属性(包括Symbol)也是对象的话递归调用
target[item] = deepClone(obj[item], hash);
} else {
target[item] = obj[item];
}
});
return target;
} |
let obj = {
a: 1,
b: 2,
c: {
c: 1,
d: 2
}
}
function deepClone(obj) {
let clone = Array.isArray(obj) ? [] : {}
for (let key of Object.keys(obj)) {
if (typeof obj[key] === 'object') {
clone[key] = deepClone(obj[key])
} else {
clone[key] = obj[key]
}
}
return clone
}
let clone = deepClone(obj)
clone.a = 1000000000
console.log(obj); |
没测试过,只求面试不要我运行 /**
* 基本数据类型是默认赋值等于拷贝,可直接返回
* 如果是对象则递归
* set Map Date RegExp Function
*/
function completeDeepClone(target){
if(typeof target != 'object' || target == null)return target;
const cloneTarget = {};
const constructor = target.constructor;
if(/^Set|Map|Date|RegExp|Function$/.test(target))return new constructor(target);
for(let key in target){
cloneTarget[key] = completeDeepClone(target[key]);
}
return cloneTarget;
} |
const mydeepClone = (target, map = new WeakMap()) => {
if (typeof target !== "object" || typeof target === "null") return target;
const constructor = target.constructor;
if (/^Date|Function|RegExp|Set|Map$/i.test(constructor.name)) {
return new constructor(target);
}
const cloneTarget = Array.isArray(target) ? [] : {};
if (map.get(target)) {
return map.get(target);
}
map.set(target, cloneTarget);
for (let key in target) {
cloneTarget[key] = mydeepClone(target[key], map);
}
return cloneTarget;
};
const target = {
field1: 1,
field2: undefined,
field3: {
child: "child",
},
field4: [2, 4, 8],
};
target.target = target;
const t1 = mydeepClone(target);
target.field3.child = "CHILD";
console.log(t1, target); |
如果Set Map里存的是对象的话,并没有深拷贝 let a = {
a:1
}
let test = {
map: new Map([['key1', 'value1'], ['key2', 'value2'], [a, a]]),
set:new Set([a])
}
let result = _completeDeepClone(test)
a.a=3
console.log(result) |
const obj = {
name: 'xiaohei',
bool: true,
nul: null,
undef: undefined,
show: function () {
console.log('show function');
},
num: 20,
set: new Set([1, 2, 3]),
map: new Map(),
date: new Date(),
reg: /.xml/g,
info: {
msg: 'old msg',
},
sym: Symbol('a'),
};
obj.obj = obj;
obj.map.set('mapKey', 'map-value');
obj.map.set('obj', obj);
const sym = Symbol('sym');
obj[sym] = 1;
const newObj = deepClone(obj);
function deepClone(target, hash = new WeakMap()) {
if (target === null) return null;
if (target instanceof Date) return new Date(target);
if (target instanceof RegExp) return new RegExp(target);
if (typeof target !== 'object') return target;
if (hash.get(target)) return hash.get(target);
if (target instanceof Set) {
const set = new Set();
hash.set(target, set);
target.forEach((value) => {
if (typeof value === 'object') {
set.add(deepClone(value, hash));
} else {
set.add(value);
}
});
return set;
}
if (target instanceof Map) {
const map = new Map();
hash.set(target, map);
for (const [key, value] of target) {
if (typeof value === 'object') {
map.set(key, deepClone(value, hash));
} else {
map.set(key, value);
}
}
return map;
}
const cloneObj = new target.constructor();
hash.set(target, cloneObj);
Reflect.ownKeys(target).forEach((key) => {
cloneObj[key] = deepClone(target[key], hash);
});
return cloneObj;
} |
function deep(target, set = new WeakSet()) { |
const _completeDeepClone = (target, map = new WeakMap()) => {
}; |
The text was updated successfully, but these errors were encountered: