2

一、需要知识点回顾

基本类型(值类型)和引用类型

(基本类型)值类型:Number,Boolean,String,undefined,null

引用类型:object,Arrary

二、基本类型和引用类型复制的区别

值类型:对值类型的复制操作,仅仅是对值的进行一份拷贝,复制与被复制的会指向两份不同的数据。

引用类型:引用类型复制的是地址。所以最后会发现,复制与被复制的最终会指向同一份数据。

例子:

// 基本类型

var a = 1;

var b = a;

a = 2;

console.log(a, b); // 2, 1 ,a b指向不同的数据
// 引用类型指向同一份数据

var a = {c: 1};

var b = a;

a.c = 2;

console.log(a.c, b.c); // 2, 2 全是2,a b指向同一份数据

三、深拷贝和浅拷贝的区别

浅拷贝:只拷贝一层。
深拷贝:无限极拷贝。

四、深度拷贝的四个例子

方法一:
function clone(source){
   if (!isObject(source)) return source;//参数校验更加优秀
     var target={};
     for(var i in source){
         if(source.hasOwnProperty(source){
              if(typeof source[i] === 'object'){ // Object.prototype.toString.call(source[i] === '[Object Object]'
                  target[i] = clone(source[i])
              }else{
                  target[i] = source[i];
              }
         }
     return target;
}
function isObject(obj){
   return Object.prototype.toString.call(obj === '[Object Object]'
}
方法二:
function cloneJSON (source){
 return JSON.parse(JSON.stringfy(source));
}

方法三:

function cloneLoop(x) {
    const root = {};
    // 栈
    const loopList = [
        {
            parent: root,
            key: undefined,
            data: x,
        }
    ];
    while(loopList.length) {
        // 深度优先
        const node = loopList.pop();
        const parent = node.parent;
        const key = node.key;
        const data = node.data;
        // 初始化赋值目标,key为undefined则拷贝到父元素,否则拷贝到子元素
        let res = parent;
        if (typeof key !== 'undefined') {
            res = parent[key] = {};
        }

        for(let k in data) {
            if (data.hasOwnProperty(k)) {
                if (typeof data[k] === 'object') {
                    // 下一次循环
                    loopList.push({
                        parent: res,
                        key: k,
                        data: data[k],
                    });
                } else {
                    res[k] = data[k];
                }
            }
        }
    }

    return root;
}
方法四:
// 保持引用关系
function cloneForce(x) {
    // =============
    const uniqueList = []; // 用来去重
    // =============
    let root = {}
    // 循环数组
    const loopList = [
        {
            parent: root,
            key: undefined,
            data: x,
        }
    ];
    while(loopList.length) {
        // 深度优先
        const node = loopList.pop();
        const parent = node.parent;
        const key = node.key;
        const data = node.data;

        // 初始化赋值目标,key为undefined则拷贝到父元素,否则拷贝到子元素
        let res = parent;
        if (typeof key !== 'undefined') {
            res = parent[key] = {};
        }
        
        // =============
        // 数据已经存在
        let uniqueData = find(uniqueList, data);
        if (uniqueData) {
            parent[key] = uniqueData.target;
            break; // 中断本次循环
        }

        // 数据不存在
        // 保存源数据,在拷贝数据中对应的引用
        uniqueList.push({
            source: data,
            target: res,
        });
        // =============
    
        for(let k in data) {
            if (data.hasOwnProperty(k)) {
                if (typeof data[k] === 'object') {
                    // 下一次循环
                    loopList.push({
                        parent: res,
                        key: k,
                        data: data[k],
                    });
                } else {
                    res[k] = data[k];
                }
            }
        }
    }

    return root;
}

function find(arr, item) {
    for(let i = 0; i < arr.length; i++) {
        if (arr[i].source === item) {
            return arr[i];
        }
    }

    return null;
}

引用文章:https://segmentfault.com/a/11...


幸福璐
70 声望12 粉丝

余生漫长,莫要慌张。