【ES6】之浅拷贝与深拷贝

浅拷贝

浅拷贝之拷贝引用地址(栈), 没有拷贝内存地址(堆)
只复制了对象的引用地址, 两个对象指向同一个内存地址, 所以修改其中任意的值, 另一个值就会随之变化(对于符合类型的数据来说, = 就是浅拷贝)

数组的浅拷贝
let arr = [1, 2, 3, 4 ,5];
let arr1 = arr;
arr1.push(6);
console.log(arr1, arr);
//(6) [1, 2, 3, 4, 5, 6] (6) [1, 2, 3, 4, 5, 6]

当对arr1的数据进行改变时, arr的数据也会相应进行改变, 因为只是改变了栈中的地址

对象的浅拷贝
let obj = {
        name: 'jiaxin',
        age: 22
}
// 浅拷贝
let obj1 = obj;
obj1.job = 'Front-end Developer';
console.log(obj1, obj);
// {name: "jiaxin", age: 22, job: "Front-end Developer"} 
// {name: "jiaxin", age: 22, job: "Front-end Developer"}

当对obj1的数据进行改变时, obj的数据也会相应进行改变, 因为只是改变了栈中的地址

深拷贝

把内存地址和引用地址都拷贝
将引用地址和内存地址都复制过来, 修改其中一个值另一个值不会改变

数组的深拷贝
 let arr2 = [...arr];
 arr2.push(7);
 console.log(arr2, arr);
 // (7) [1, 2, 3, 4, 5, 6, 7] (6) [1, 2, 3, 4, 5, 6]

当改变arr2中的内容时, arr的内容不会改变, 因为深拷贝拷贝了内存地址和引用地址

// 循环遍历数组
let arr3 = [];
for(let k in arr){
   arr3[k] = arr[k];
}
arr3.push(8);
console.log(arr3, arr);
// (7) [1, 2, 3, 4, 5, 6, 8] (6) [1, 2, 3, 4, 5, 6]
对象的深拷贝
let obj = {
   name: 'jiaxin',
   age: 22
}
//深拷贝
let obj2 = {};

 for(let k in obj){
   obj2[k] = obj[k];
}

obj2.gender = 'female';
console.log(obj2, obj);

//{name: "jiaxin", age: 22, job: "Front-end Developer", gender: "female"}
//{name: "jiaxin", age: 22, job: "Front-end Developer"}
深度克隆函数封装
    let arr = [1, 2, 3, 4, 5];
    let obj = {
        name: 'jiaxin',
        age: 22
    }

    // 封装函数
    function deepClone(object) {
        // 定义一个新变量
        let newObj;
        // 判断object的类型
        if(Object.prototype.toString.call(object) === "[object Array]"){
            // 数组
            newObj = [];
        }else if(Object.prototype.toString.call(object) === "[object Object]"){
            // 对象
            newObj = {}
        }
        // 遍历赋值
        for(let k in object){
            newObj[k] = object[k];
        }

        return newObj;
    }

    // 函数调用
    // 数组
    let newArr = deepClone(arr);
    newArr.push(12345)
    console.log(newArr, arr);
    // (6) [1, 2, 3, 4, 5, 12345] (5) [1, 2, 3, 4, 5]

    // 对象
    let newObj = deepClone(obj);
    newObj.gender = "female";
    console.log(newObj, obj);
    // {name: "jiaxin", age: 22, gender: "female"} {name: "jiaxin", age: 22}

Leetcode133 Clone Graph

给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。

图中的每个节点都包含它的值 val(int) 和其邻居的列表(list[Node])。

class Node {
    public int val;
    public List<Node> neighbors;
}
解题思路
  • 拷贝所有节点
  • 拷贝所有边
解题步骤
  • 深度或者广度优先遍历所有节点
  • 拷贝所有节点并存储
  • 将拷贝的节点按照原图的连接方法连接
dfs深度优先遍历
/**
 * // Definition for a Node.
 * function Node(val, neighbors) {
 *    this.val = val === undefined ? 0 : val;
 *    this.neighbors = neighbors === undefined ? [] : neighbors;
 * };
 */

/**
 * @param {Node} node
 * @return {Node}
 */
var cloneGraph = function(node) {
      // 判断节点是否为空
      if(!node) return;
      // 对每个节点进行深度优先遍历dfs
      // 访问过的节点以Map形式存储
      const visited = new Map();
      const dfs = (n) => {
          //console.log(n.val);
          const nCopy = new Node(n.val);
          visited.set(n, nCopy);
          (n.neighbors || []).forEach(ne => {
              if(!visited.has(ne)){
                  dfs(ne);
              }
              // 克隆边
              nCopy.neighbors.push(visited.get(ne));
          });
      };
      dfs(node);
      // 返回第一个节点的拷贝
      return visited.get(node);
};
广度优先遍历
var cloneGraph = function(node) {
      // 判断节点是否为空
      if(!node) return;
      
      // 广度优先遍历每一个节点
      const visited = new Map();
      const q = [node];
      // 标记第一个节点
      visited.set(node, new Node(node.val));
      while(q.length){
          // 首先获取队头
          const n = q.shift();
          //console.log(n.val);
          // 遍历每一个邻居节点
          (n.neighbors || []).forEach(ne =>{
              // 如果没有被访问过
              if(!visited.has(ne)){
                 q.push(ne);
                 visited.set(ne, new Node(ne.val));
              }
              // 克隆边
            visited.get(n).neighbors.push(visited.get(ne));
          })
      }
      return visited.get(node);
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值