美文网首页
实现深、浅拷贝

实现深、浅拷贝

作者: 欢欣的膜笛 | 来源:发表于2021-05-10 16:59 被阅读0次

数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型。
基本数据类型的特点:直接存储在栈(stack)中的数据
引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里

引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

实现浅拷贝

// 实现方式一:Object.assign
let target = {};
let source = {
    a: '123',
    b: { name: 'yd' }
};
Object.assign(target, source);
console.log(target); // { a: '123', b: { name: 'yd' } }

// 实现方式二:Array.prototype.slice、Array.prototype.concat
let array = [{ a: 1 }, { b: 2 }];
console.log(array.slice(0)); // [{a: 1}, {b: 2}]
console.log([].concat(array)); // [{a: 1}, {b: 2}]

// 实现方式三:扩展运算符
let obj = {
    a: 1,
    b: { c: 1 }
};
console.log({ ...obj }); // { a: 1, b: { c: 1 } }

// 实现方式四:
function cloneShallow(source) {
    let target = {};
    for (let key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
            target[key] = source[key];
        }
    }
    return target;
}

实现深拷贝

// 实现方式一:JSON.stringify
/*
 * 缺点:
 * 1、日期类型的数据会直接变成字符串的形式,而不是对象的形式
 * 2、正则类型的数据会变成空对象{}
 * 3、函数会丢失
*/

// 实现方式二:自定义实现深拷贝函数
function cloneDeep(data) {
    // 当 null NaN undefined number string 等基本数据类型时直接返回
    if (data === null || typeof data !== 'object') {
        return data
    }

    // Date类型
    if (data instanceof Date) {
        return new Date(data.valueOf())
    }

    // 正则类型
    if (data instanceof RegExp) {
        return new RegExp(data)
    }

    // Map 集合
    if (data instanceof Map) {
        let m = new Map()
        data.forEach((v, k) => m.set(k, cloneDeep(v)))
        return m
    }

    // Set 集合
    if (data instanceof Set) {
        let s = new Set()
        for (let val of data.values()) {
            s.add(cloneDeep(val))
        }
        return s
    }

    // 数组、对象等引用数据类型
    if (typeof data === 'object') {
        const copyData = Array.isArray(data) ? [] : {}
        for (const key in data) {
            if (data.hasOwnProperty(key)) {
                copyData[key] = cloneDeep(data[key])
            }
        }
        return copyData
    }

    // 函数
    if (data instanceof Function) {
        return (new data()).constructor
    }

    return data
}

// 实现方式三:使用 lodash.js 中的 cloneDeep 函数

实现 JSON(parse + stringify)

if (!window.JSON) {
    window.JSON = {
        parse: function (sJSON) {
            return eval('(' + jsonStr + ')');
            // return new Function('return ' + jsonStr)();
        },
        stringify: (function () {
            var toString = Object.prototype.toString;
            var isArray = Array.isArray || function (array) {
                return toString.call(array) === '[object Array]'
            };
            var escMap = {
                '"': '\\"',
                "\\": "\\\\",
                "\b": "\\b",
                "\f": "\\f",
                "\n": "\\n",
                "\r": "\\r",
                "\t": "\\t",
            };
            var escFunc = function (m) {
                return escMap[m] || "\\u" + (m.charCodeAt(0) + 0x10000).toString(16).substr(1);
            };
            var escRE = /[\\"\u0000-\u001F\u2028\u2029]/g;
            return function stringify(value) {
                if (value == null) {
                    return 'null';
                } else if (typeof value === 'number') {
                    // isFinite() 函数用于检查其参数是否是无穷大,如果参数是 NaN,正无穷大或者负无穷大,会返回 false,其他返回 true。
                    return isFinite(value) ? value.toString() : 'null';
                } else if (typeof value === 'boolean') {
                    return value.toString();
                } else if (typeof value === 'object') {
                    if (typeof value.toJSON === 'function') {
                        return stringify(value.toJSON());
                    } else if (isArray(value)) {
                        var res = '[';
                        for (var i = 0; i < value.length; i++) {
                            res += (i ? ', ' : '') + stringify(value[i]);
                        }
                        return res + ']';
                    } else if (toString.call(value) === '[object Object]') {
                        var tmp = [];
                        for (var k in value) {
                            if (value.hasOwnProperty(k)) {
                                tmp.push(stringify(k) + ': ' + stringify(value[k]));
                            }
                        }
                        return '{' + tmp.join(', ') + '}';
                    }
                }
                return '"' + value.toString().replace(escRE, escFunc) + '"';
            };
        })(),
    };
}

相关文章

  • 深拷贝、浅拷贝

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

  • 面试题整理

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

  • js浅拷贝深拷贝

    js浅拷贝,深拷贝的简单实现 基础数据 浅拷贝 深拷贝

  • 面试 (一) : 基础篇

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

  • 基础

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

  • 常见的面试(一)

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

  • 五、面试总结(五)

    对象 拷贝(clone) 如何实现对象克隆 深拷贝和浅拷贝区别 深拷贝和浅拷贝如何实现激活机制 写clone()方...

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

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

  • Object 对象

    什么是浅拷贝,如何实现浅拷贝?什么是深拷贝,如何实现深拷贝? 是什么: 浅拷贝: 将原对象或原数组的引用直接赋给新...

  • js深拷贝浅拷贝

    目录 一.数据类型 二.浅拷贝与深拷贝 三.赋值和浅拷贝的区别 四.浅拷贝的实现方式 五.深拷贝的实现方式 一.数...

网友评论

      本文标题:实现深、浅拷贝

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