美文网首页计算机语言
手写源码-实现深拷贝

手写源码-实现深拷贝

作者: 胡小喵_ | 来源:发表于2021-08-31 11:28 被阅读0次

实现一个深拷贝,包括 Symbol 类型及 Regexp(正则)的拷贝

  1. 初级版
// 数据类型 
let target = {
   field1: 1,
   field2: undefined,
   field3: 'field3',
   field4: {
     child1: {
       _child1: 1
     },
     child2: '2'
   }
 };

// 代码实现
function deepClone(target) {
    if (Object.prototype.toString.call(target) == '[object Object]') {
        let cloneTarget = {};
        Object.keys(target).forEach(key => {
            const item = target[key];
            cloneTarget[key] = deepClone(item);
        });
        return cloneTarget;
    }
    return target;
}
  1. 终极版:可处理循环引用
// 数据类型 
let target = {
   field1: 1,
   field2: undefined,
   field3: 'field3',
   field4: {
     child1: {
       _child1: 1
     },
     child2: '2'
   }
 };
target.target = target;

function deepClone(target, map = new WeakMap()) {
    if (
        Object.prototype.toString.call(target) == '[object Object]' ||
        Object.prototype.toString.call(target) == '[object Array]'
    ) {
        let cloneTarget = Object.prototype.toString.call(target) == '[object Object]' ? {} : [];
        if (map.get(target)) {
            return target;
        }
        map.set(target, cloneTarget);
        Object.keys(target).forEach(key => {
            const item = target[key];
            cloneTarget[key] = deepClone(item, map);
        });
        return cloneTarget;
    }
    return target;
}
  1. 把 forEach 转换为 性能更好的 while
function _forEach(array, fn) {
    let index = -1,
        len = array.length;
    while (++index < len) {
        fn(array[index], index, array);
    }
}

function deepClone(target, map = new WeakMap()) {
    if (
        Object.prototype.toString.call(target) == '[object Object]' ||
        Object.prototype.toString.call(target) == '[object Array]'
    ) {
        let cloneTarget = Object.prototype.toString.call(target) == '[object Object]' ? {} : [];
        if (map.get(target)) {
            return target;
        }
        map.set(target, cloneTarget);
        _forEach(Object.keys(target), key => {
            const item = target[key];
            cloneTarget[key] = deepClone(item, map);
        });
        return cloneTarget;
    }
    return target;
}

究极版

let target = {
    field1: 1,
    field2: undefined,
    field3: 'field3',
    field4: {
        child1: {
            _child1: 1
        },
        child2: '2'
    },
    field4: [1, 2, 3],
    reg: /\w*$/g
};
target.target = target;

let TAG_MAP_FUN = {};
function setTagsMap() {
    ['Set', 'Map', 'Object', 'Array', 'Function', 'RegExp', 'Symbol'].forEach(key => {
        TAG_MAP_FUN['is' + key] = function () {
            return Object.prototype.toString.call(arguments[0]) == `[object ${key}]`;
        };
    });
}
setTagsMap();

// 引用类型 和 null 的 typeof 都为 object
function isReference(target) {
    const type = typeof target;
    return target !== null && (type === 'object' || type === 'function');
}

function getInit(target) {
    const Cons = target.constructor;
    return new Cons();
}

function deepClone(target, map = new WeakMap()) {
    if (TAG_MAP_FUN.isRegExp(target)) {
        let newTarget = target.constructor(target.source, /\w*$/.exec(target));
        newTarget.lastIndex = target.lastIndex;
        return newTarget;
    }
    if (!isReference(target) || TAG_MAP_FUN.isFunction(target)) {
        return target;
    }

    // 引用类型
    let cloneTarget = getInit(target);

    // 放置引用类型循环引用
    if (map.get(target)) {
        return target;
    }
    map.set(target, cloneTarget);

    if (TAG_MAP_FUN.isSet(target)) {
        target.forEach(value => {
            cloneTarget.add(deepClone(value, map));
        });
    }
    if (TAG_MAP_FUN.isMap(target)) {
        target.forEach((value, key) => {
            cloneTarget.set(key, deepClone(value, map));
        });
    }
    if (TAG_MAP_FUN.isObject(target) || TAG_MAP_FUN.isArray(target)) {
        Object.keys(target).forEach(key => {
            const value = target[key];
            cloneTarget[key] = deepClone(value, map);
        });
    }

    return cloneTarget;
}

let newTarget = deepClone(target);

相关文章

  • 手写源码-实现深拷贝

    实现一个深拷贝,包括 Symbol 类型及 Regexp(正则)的拷贝 初级版 终极版:可处理循环引用 把 for...

  • 深入JavaScript Day33 - 序列化实现深拷贝的缺点

    一、序列化实现深拷贝的缺点、手写深拷贝 1、借助序列化实现深拷贝,有哪些缺点? ①不能拷贝函数 ②不能拷贝Symb...

  • 手写深拷贝

    手写深拷贝 深拷贝 深拷贝简单理解就是b是a的一份拷贝,且b中不存在a中对象的引用 深拷贝的实现 1.JSON序列...

  • 手写一个深拷贝(深克隆)

    1. 首先使用JSON.parse来实现一个深拷贝 2. 手写实现深拷贝 测试发现两种效果是一样的,深拷贝完成。

  • iOS基础知识点(网络摘抄)

    1.父类实现深拷贝时,子类如何实现深拷贝。父类没有实现深拷贝时,子类如何实现深拷贝? 深拷贝同浅拷贝的区别:...

  • 深拷贝、浅拷贝

    父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。 深拷贝同浅拷贝的区别:浅拷贝...

  • 面试题整理

    父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。 深拷贝同浅拷贝的区别:浅拷贝...

  • iOS面试基础一

    #父类实现深拷贝时,子类如何实现深度拷贝.父类没有实现深拷贝时,子类如何实现深度拷贝.# <(1)深拷贝同浅拷贝的...

  • 0. iOS面试题基础篇

    1. 父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。 1.1 深拷贝同浅拷贝...

  • iOS基础知识点01

    1. 父类实现深拷贝时,子类如何实现深度拷贝。父类没有实现深拷贝时,子类如何实现深度拷贝。 1.1 深拷贝同浅拷贝...

网友评论

    本文标题:手写源码-实现深拷贝

    本文链接:https://www.haomeiwen.com/subject/eucziltx.html