前端重点面试题 --【 拷贝 】

38 阅读3分钟

在日常开发及面试过程中,总是可以涉及到数据的拷贝。浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。深拷贝是新开辟一个新的地址空间,新旧对象不共享内存,修改新对象不会改变原对象。 本期内容带你深入了解javascript 的拷贝。

基础知识

在理解 深拷贝 和 浅拷贝之前 ,我们先了解下JavaScript有哪些类型:

  1. 基本数据类型 : Number、String、Boolean、undefined、Null、以及Es6新特性Symbol、或者Es10中的Bigint( BigInt是一种新的数据类型,用于当整数值大于Number数据类型支持的范围时。这种数据类型允许我们安全地对大整数执行算术操作,表示高分辨率的时间戳,使用大整数id,等等,而不需要使用库。Bigint )。
  2. 引用数据类型: 对象Object(包含普通对象-Object,数组对象-Array,正则对象-RegExp,日期对象-Date,数学函数-Math,函数对象-Function)。

浅拷贝 和 深拷贝 ?

浅拷贝:拷贝的是引用地址,如果地址内的内容发生改变,所有的内容也会相应的改变。

    // 赋值拷贝
    let obj = {a:1};
    let obj1 = obj;
    obj1.a = 2;
    console.log(obj); // {a:2}
    
    // 循环拷贝
    let obj = {
       name:'a',
       age:18,
       fruit:{
         apply:5
       }
    }
    let obj2 = {};
    for(let key in obj){
        obj2[key] = obj[key];
    }
    obj2.name = 'b';
    obj2.fruit.apply = 8;
    console.log(obj); // {name: 'a', age: 18, fruit: {apply: 8}}
    console.log(obj2); // {name: 'b', age: 18, fruit: {apply: 8}}
    
    // Object.assign()
    let obj = {
       name:'a',
       age:18,
       fruit:{
         apply:5
       }
    }
    let obj3 = Object.assign({}, obj);
    obj3.name = 'd';
    obj3.fruit.apply = 8;
    console.log(obj); // {name: 'a', age: 18, fruit: {apply: 8}}
    console.log(obj3); // {name: 'd', age: 18, fruit: {apply: 8}}
    
    // 拓展运算符
    let obj = {
       name:'a',
       age:18,
       fruit:{
         apply:5
       }
    }
    let obj4 = {...obj};
    obj4.name = 'e';
    obj4.fruit.apply = 8;
    console.log(obj); // {name: 'a', age: 18, fruit: {apply: 8}}
    console.log(obj4); // {name: 'e', age: 18, fruit: {apply: 8}}
      

深拷贝:拷贝的是对象或者数组内部数据的属性值,在堆中开辟属于自己的内存区域。

 // JSON.parse(JSON.stringify());
 let obj = {
   name:'a',
   age:18,
   fruit:{
     apply:5
   }
 }
 let newobj = JSON.parse(JSON.stringify(obj));
 newobj.fruit.apply = 8;
 console.log(obj); // {name: 'a', age: 18, fruit: {apply: 5}}
 console.log(newobj); // {name: 'a', age: 18, fruit: {apply: 8}}
 

JSON 只支持object、array 、string、number、true、false、null 这几种数据或者值,其他的比如函数,undefined、Date、RegExp 等数据类型都不支持,对于它不支持的数据都会直接忽略该属性。

  1. 函数
  let obj = {
   name:'a',
   age:18,
   fruit:{
     apply:5
   },
   b:[1,2,3],
   c:function(){
     console.log('我是函数');
   }
 }
 let newobj = JSON.parse(JSON.stringify(obj));
 console.log(newobj);
 // { "name": "a", "age": 18, "fruit": {"apply": 5},"b": [1,2,3]}
  1. undefined
let obj = {
   a:undefined
 }
 let newobj = JSON.parse(JSON.stringify(obj));
 console.log(newobj); // {}
  1. RegExp
 let obj = {
   a:/[0-9]+/
 }
 let newobj = JSON.parse(JSON.stringify(obj));
 console.log(newobj); // {"a": {}}
  1. Date
 let obj = {
   a:new Date()
 }
 let newobj = JSON.parse(JSON.stringify(obj));
 console.log(newobj); // {"a": "2022-07-29T08:52:12.633Z"}
 console.log(newobj.getTime()) // newobj.getTime is not a function
  1. 环状结构的对象 (环就是对象循环引用,导致自己成为一个闭环)
 let obj = {name:'a'};
 obj.age = obj;
 let newobj = JSON.parse(JSON.stringify(obj));
 console.log(newobj); //  Converting circular structure to JSON -->   starting at object with constructor 'Object' --- property 'age' closes the circle at JSON.stringify 
 // 递归
 let obj = {
   name:'a',
   age:18,
   fruit:{
     apply:5
   }
 }
 function deepClone(obj) {
    var target = {};
    for(var key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            if (typeof obj[key] === 'object') {
                target[key] = deepClone(obj[key]); 
            } else {
                target[key] = obj[key];
            }
        }
    }
    return target;
}
let newobj= deepClone(obj);
newobj.fruit.apply = 8;
console.log(obj); // {name: 'a', age: 18, fruit: {apply: 5}}
console.log(newobj); // {name: 'a', age: 18, fruit: {apply: 8}}
 

后记

以上就是本期 拷贝 相关的内容,希望对小伙伴们更好的掌握这方面的知识点有些许帮助,不要忘了来个点赞哦 👍 ~~。有任何问题还望各位大佬批评指正,谢谢!后续持续更新。。。