-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
[js] 第44天 深度克隆对象的方法有哪些,并把你认为最好的写出来 #167
Comments
我比较喜欢使用原生的方法,足够简单,而且可以解决大多数的深拷贝。
|
是挺好的, 就是容易出bug |
递归调用拷贝。json.parse可以解决一般的对象深拷贝,但是函数类型的对象就不行了 |
全面的deep clone最坑爹的一点就是对象内部引用自己 |
// 深度遍历
// 广度遍历 |
数组: newArr=[...oldArr] |
对一维数组,才能使用newArr=[...oldArr] |
数组clone:Array.from( ) |
function deepClone(obj) {
if (Object.prototype.toString.call(obj).slice(8, -1) === 'Object') {
var newObj = {}
for (const key in obj) {
newObj[key]=deepClone(obj[key])
}
return newObj
} else if (Object.prototype.toString.call(obj).slice(8, -1) === 'Array') {
var newArr = []
for (const index in obj) {
newArr[index]=deepClone(obj[index])
}
return newArr
}
return obj
} |
const isType = type => target =>
Object.prototype.toString.call(target) === `[object ${type}]`
const isArray = isType('Array')
const isObject = isType('Object')
function extend(target, source, deep) {
for (const key in source)
if (source.hasOwnProperty(key))
if (deep && (isArray(source[key]) || isObject(source[key]))) {
if (isArray(source[key]) && !isArray(target[key])) target[key] = []
if (isObject(source[key]) && !isObject(target[key])) target[key] = {}
extend(target[key], source[key], deep)
} else if (source[key] !== undefined) target[key] = source[key]
}
function clone(target) {
let deep,
args = [].slice.call(arguments, 1)
if (typeof target === 'boolean') {
deep = target
target = args.shift()
}
args.forEach(source => extend(target, source, deep))
return target
} |
我习惯用json.parser(json.stringify()), |
这个小老弟, 扩展运算符那个是浅拷贝,深拷贝最简单的是 JSON.parse JSON.stringify 但对于 undefined function symbol 是会忽略的。 你API层面得到的都是浅拷贝。 通常来说,都是递归来实现一个 deepClone |
function deepCopy(newObj, oldObj) {
for (var key in oldObj) {
var item = oldObj[key]
if (item instanceof Array) {
newObj[key] = [];
deepCopy(newObj[key], item);
}
else if (item instanceof Object) {
newObj[key] = {};
deepCopy(newObj[key], item);
}
else {
newObj[key] = item;
}
}
return newObj;
} |
function deepCopy(source, target) {
const c = target || {}
for (const item in source) {
if (typeof source[item] === 'object') {
c[item] = (source[item].constructor === Array) ? [] : {}
deepCopy(source[item], c[item])
} else {
c[item] = source[item]
}
}
return c
} |
|
递归实现function cloneDeep(source) {
var temp = source.constructor == Array ? [] : {};
for (var keys in source) {
if (source.hasOwnProperty(keys)) {
if (source[keys] && typeof source[keys] === 'object') {
temp[keys] = source[keys].construct === Array ? [] : {};
temp[keys] = cloneDeep(source[keys]);
} else {
temp[keys] = source[keys]
}
}
}
return temp;
} |
|
deepClone = (element) => {
if(!(typeof element === 'object')) return element;
if(element === null) return null;
return element instanceof Array
? element.map(item => deepClone(item))
: Object.entries(element)
.reduce((pre,[key,val])=> ({...pre, [key]: deepClone(val)}), {});
}
//
const test1 = [1,[2],[[3]],{a:1},{b:{c:1}}];
const test2 = {a: [1], b: {c: 2}};
console.log(test1, deepClone(test1));
console.log(test2, deepClone(test2)); |
|
简单的拷贝递归拷贝 ==>解决了循环引用
function _clone(target, map = new Map()) {
if (typeof target !== 'object') {
return target;
}
let clonetarget = target instanceof Array ? [] : {}
if (map.has(target)) {
return map.get(target);
}
map.set(target, clonetarget);
for (const key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) {
clonetarget[key] = typeof target[key] === 'object' ? _clone(target[key], map) : target[key];
}
}
return clonetarget;
} 完整点的const mapTag = '[object Map]';
const setTag = '[object Set]';
const arrayTag = '[object Array]';
const objectTag = '[object Object]';
const argsTag = '[object Arguments]';
const boolTag = '[object Boolean]';
const dateTag = '[object Date]';
const numberTag = '[object Number]';
const stringTag = '[object String]';
const symbolTag = '[object Symbol]';
const errorTag = '[object Error]';
const regexpTag = '[object RegExp]';
const funcTag = '[object Function]';
const deepTag = [mapTag, setTag, arrayTag, objectTag, argsTag];
function forEach(array, iteratee) {
let index = -1;
const length = array.length;
while (++index < length) {
iteratee(array[index], index);
}
return array;
}
function isObject(target) {
const type = typeof target;
return target !== null && (type === 'object' || type === 'function');
}
function getType(target) {
return Object.prototype.toString.call(target);
}
function getInit(target) {
const Ctor = target.constructor;
return new Ctor();
}
function cloneSymbol(targe) {
return Object(Symbol.prototype.valueOf.call(targe));
}
function cloneReg(targe) {
const reFlags = /\w*$/;
const result = new targe.constructor(targe.source, reFlags.exec(targe));
result.lastIndex = targe.lastIndex;
return result;
}
function cloneFunction(func) {
const bodyReg = /(?<={)(.|\n)+(?=})/m;
const paramReg = /(?<=\().+(?=\)\s+{)/;
const funcString = func.toString();
if (func.prototype) {
const param = paramReg.exec(funcString);
const body = bodyReg.exec(funcString);
if (body) {
if (param) {
const paramArr = param[0].split(',');
return new Function(...paramArr, body[0]);
} else {
return new Function(body[0]);
}
} else {
return null;
}
} else {
return eval(funcString);
}
}
function cloneOtherType(targe, type) {
const Ctor = targe.constructor;
switch (type) {
case boolTag:
case numberTag:
case stringTag:
case errorTag:
case dateTag:
return new Ctor(targe);
case regexpTag:
return cloneReg(targe);
case symbolTag:
return cloneSymbol(targe);
case funcTag:
return cloneFunction(targe);
default:
return null;
}
}
function clone(target, map = new WeakMap()) {
// 克隆原始类型
if (!isObject(target)) {
return target;
}
// 初始化
const type = getType(target);
let cloneTarget;
if (deepTag.includes(type)) {
cloneTarget = getInit(target, type);
} else {
return cloneOtherType(target, type);
}
// 防止循环引用
if (map.get(target)) {
return target;
}
map.set(target, cloneTarget);
// 克隆set
if (type === setTag) {
target.forEach(value => {
cloneTarget.add(clone(value));
});
return cloneTarget;
}
// 克隆map
if (type === mapTag) {
target.forEach((value, key) => {
cloneTarget.set(key, clone(value));
});
return cloneTarget;
}
// 克隆对象和数组
const keys = type === arrayTag ? undefined : Object.keys(target);
forEach(keys || target, (value, key) => {
if (keys) {
key = value;
}
cloneTarget[key] = clone(target[key], map);
});
return cloneTarget;
} |
|
|
学习了。 /** 将目标对象克隆到一个新对象
* @param target {Object.Array} 克隆到的最新对象或数组
* @param source {Object.Array} 被克隆的原始对象或数组。它要与 target 的类型保持一致。
* @param deep {Boolean} 深克隆的标识。true: 深克隆; false(默认): 浅克隆。
* @return void
*/
extend(target, source, deep) |
`<script>
</script>` |
function deepClone(target){ 最好的感觉还是Json.stringify(obj) |
function deepClone(obj){
if(!obj instanceof Object ) return;
let target = Array.isArray(obj) ? [] : {};
for(let key in obj){
if(obj.hasOwnPrototype(key)){
if(type obj[key] === 'object'){
target[key] = deepClone(obj[key]);
}else{
target[key] = obj[key];
}
}
}
return target;
} |
第44天 深度克隆对象的方法有哪些,并把你认为最好的写出来
The text was updated successfully, but these errors were encountered: