JS每日一题:深拷贝与浅拷贝的区别?如何实现一个深拷贝

20190311期

深拷贝与浅拷贝的区别?如何实现一个深拷贝jquery

在回答这个问题前,咱们先来回顾一下JS中两大数据类型git

  • 基本类型 Undefined、Null、Boolean、Number、String
  • 引用类型 Object Array
基本类型

基本类型就是值类型, 存放在栈(stack)内存中的简单数据段,数据大小肯定,内存空间大小能够分配github

引用类型

引用类型, 存放在堆(heap)内存中的对象,变量实际保存的是一个指针,这个指针指向另外一个位置函数

根据上面的分析,咱们分别是两处类型作一个copy处理oop

let obj = {
    name: '每日一题',
    value: 'JS'
}

let obj2 = obj
let obj3 = obj.name

console.log(obj2.value) //JS
console.log(obj3) // 每日一题

// 改变obj2,obj3
obj2.value = 'CSS'
obj3 = 'HTML'

console.log(obj.value) // CSS
console.log(obj.name) // 每日一题

从上面的输出结束来看,咱们能够猜想obj,obj2操做的是同一个对象,而obj和obj3是彻底独立的, 说到这里就进入了深浅拷贝学习

浅拷贝

概念: 对于字符串类型,浅拷贝是对值的复制,对于对象来讲,浅拷贝是对对象地址的复制, 也就是拷贝的结果是两个对象指向同一个地址

基本概念回过头去看上面的代码咱们就能分析出来其都是浅复制大数据

深拷贝

概念: 深拷贝开辟一个新的栈,两个对象对应两个不一样的地址,修改一个对象的属性,不会改变另外一个对象的属性

如何实现深拷贝

JSON.stringify()

首先安利一个无脑黑科技骚操做
* 缺点: JSON.stringify()没法正确处理函数翻译

let obj = {
    name: '每日一题',
    value: 'JS'
}
console.log(JSON.parse(JSON.stringify(obj))) // 深拷贝了一份obj

let obj = {
    name: '每日一题',
    value: 'JS',
    fn: function(){}
}
console.log(JSON.parse(JSON.stringify(obj))) // obj.fn 丢失
递归

讲到深copy不少人都会想到extend方法,没错,这玩意deep为true确实能深copy,咱们就过来翻一翻他的源码指针

这边以你们熟悉的jquery为例code

// 源码地址 https://github.com/jquery/jquery/blob/5bdc85b82b84e5459462ddad9002f22d1ce74f21/src/core.js#L125

// 只取核心逻辑代码,感兴趣的能够自行去源码地址查看具体实现
// 有英文注释,我就不蹩脚翻译了
// 总体思路就是递归对象,判断类型,处理类型
    for ( ; i < length; i++ ) {

        // Only deal with non-null/undefined values
        if ( ( options = arguments[ i ] ) != null ) {

            // Extend the base object
            for ( name in options ) {
                copy = options[ name ];

                // Prevent never-ending loop
                if ( target === copy ) {
                    continue;
                }

                // Recurse if we're merging plain objects or arrays
                if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
                    ( copyIsArray = Array.isArray( copy ) ) ) ) {
                    src = target[ name ];

                    // Ensure proper type for the source value
                    if ( copyIsArray && !Array.isArray( src ) ) {
                        clone = [];
                    } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
                        clone = {};
                    } else {
                        clone = src;
                    }
                    copyIsArray = false;

                    // Never move original objects, clone them
                    target[ name ] = jQuery.extend( deep, clone, copy );

                // Don't bring in undefined values
                } else if ( copy !== undefined ) {
                    target[ name ] = copy;
                }
            }
        }
    }

总结

  • 浅拷贝是复制,两个对象指向同一个地址
  • 深拷贝是新开栈,两个对象指向不一样的地址

关于JS每日一题

JS每日一题能够当作是一个语音答题社区
天天利用碎片时间采用60秒内的语音形式来完成当天的考题
群主在第二天0点推送当天的参考答案

  • 注 毫不仅限于完成当天任务,更可能是查漏补缺,学习群内其它同窗优秀的答题思路

点击加入答题

相关文章
相关标签/搜索