美文网首页
深拷贝/浅拷贝

深拷贝/浅拷贝

作者: 采姑娘的小智障 | 来源:发表于2020-05-30 15:30 被阅读0次

深浅拷贝

数据类型及特点

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

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

深浅拷贝

深浅拷贝只针对Object或者Array这样的引用数据类型

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

浅拷贝与赋值的区别

var obj1 = {name: 'LiLy', age: '12', language: ['english', 'chinese', 'frech']}
  • 赋值: 赋的是该对象在栈中的地址,而不是堆中的数据。
    两个对象指向的是同个存储空间,无论哪个对象发生改变,其实改变的都是原对象,是联动的。

          var obj2 = obj1
          obj2.name = 'Lucy'
          obj2.language[0] = 'India'
          
          obj1 和 obj2 都是
          
          {
              age: "12"
              language: (3) ["India", "chinese", "frech"]
              name: "Lucy"
           }
    
  • 浅拷贝:按位拷贝对象,它会创建一个对象,这个对象有着原始对象属性值的一份精确拷贝。
    如果属性是基本数据类型,拷贝的就是基本类型的值;
    如果属性是引用数据类型,拷贝的就是内存地址。
    因此如果其中一个对象改变了这个内存地址,就会影响到另一个对象

function shallowCopy(src) {
    var dst = {}
    for (var prop in src) {
        if (src.hasOwnProperty(prop)) {
            dst[prop] = src[prop]
        }
    }
    return dst
}

var obj3 = shallowCopy(obj1)

obj3.name = 'Bob'
obj3.language[0] = 'lan3'

obj3: {
      age: "12"
      language: (3) ["lan3", "chinese", "frech"]
      name: "Bob"
}

obj1: {
    age: "12"
    language: (3) ["lan3", "chinese", "frech"]
    name: "Lucy"
}

总结:

-- 和原数据是否指向同个对象 第一层数据为基本数据类型 元数据中包含子对象
赋值 改变会使原数据一同改变 改变会使原数据一同改变
浅拷贝 改变不会使原数据一同改变 改变会使原数据一同改变
深拷贝 改变不会使原数据一同改变 改变不会使原数据一同改变

浅拷贝实现方式

  1. Object.assign()

把任意多个源对象的可枚举属性,拷贝给目标对象,然后返回目标对象。其中拷贝的是对象属性的引用,而不是对象属性身。

var obj1= {
    age: "12",
    language: (3) [1, 2, 3],
    name: "a",
    love: {son: 'tom'}
};
        
var obj2=Object.assign({}, obj1);  // obj2: {age: "12", language: undefined, name: "a",love: {son: "tom"}}

obj2.love.son='Bob';              // obj2: {age: "12", language: undefined, name: "a",love: {son: "Bob"}}, obj1: {age: "12", language: undefined, name: "a",love: {son: "Bob"}}

// 当object 只有一层的时候,是深拷贝
obj2.age='13'                   // obj2: {age: "13", language: undefined, name: "a"}, obj1: {age: "12", language: undefined, name: "a"}
  1. Array.prototype.concat()

修改新对象的子对象会改到原对象

var arr1=[1,2,{name: 'a1'}];
var arr2=arr1.concat();  // arr2: [1,2,{name: 'a1'}]
arr2[1] = 3;             // arr1:[1,2,{name: 'a1'}], arr2: [1,3,{name: 'a1'}]
arr2[2].name='a2';       // arr1:[1,2,{name: 'a2'}], arr2: [1,3,{name: 'a2'}]
  1. Array.prototype.slice()

修改新对象的子对象会改到原对象

var arr1=[1,2,{name: 'a1'}];
var arr2=arr1.slice();  // arr2: [1,2,{name: 'a1'}]
arr2[1] = 3;             // arr1:[1,2,{name: 'a1'}], arr2: [1,3,{name: 'a1'}]
arr2[2].name='a2';       // arr1:[1,2,{name: 'a2'}], arr2: [1,3,{name: 'a2'}]     

深拷贝实现方式

  1. JSON.parse(JSON.stringfy())
    先转换成JSON字符串再转成JSON对象,会产生新的对象,而且对象会开辟新的栈,实现深拷贝。

注意: 不能处理函数,因为JSON.stringfy()不能结束函数,转化结果为null

var arr = [1, 3, {
    username: ' kobe'
}];

var arr4 = JSON.parse(JSON.stringify(arr));

arr4[2].username = 'duncan';   // arr4:[1, 3, {username: 'duncan'}], arr: [1, 3, {username: 'kobe'}]

arr4[1]=2;                    // arr4:[1, 2, {username: 'duncan'}], arr: [1, 3, {username: 'kobe'}]
  1. 函数库lodash

_.cloneDeep函数实现深拷贝

var obj1={a: 's', {name: 'Lily'}};

var obj2 = _.cloneDeep(obj1); 
  1. 手写递归方法

遍历对象,数组,直到里面都是基本数据类型,再进行复制

function checkedType (target) {
    return Object.prototype.toString.call(target).slice(8, -1)
}

function clone (target) {
    // result 为最后返回的结果, tartgetType为目标数据类型
    let result, tartgetType = checkedType(target)
    
    if (tartgetType === 'Array') {
        result = []
    } else if (tartgetType === 'Object') {
       result = {}
   } else {
       // 基本数据类型,直接返回结果
        return target
   }
   
    for (var key in target) {
        // 遍历对象或数组,直到找到基本数据类型进行复制
        let value = target[key]
        if (checkedType(value) === 'Object' || checkedType(value) === 'Array') {
             //继续遍历获取到value值
              result[i] = clone(value)
        } else {
            result[i] = value
        }
    }
    return result
}    

相关文章

  • iOS深拷贝(MutableCopy)与浅拷贝(Copy)的区别

    深拷贝和浅拷贝的概念 iOS中有深拷贝和浅拷贝的概念,那么何为深拷贝何为浅拷贝呢?浅拷贝:浅拷贝并不拷贝对象本身,...

  • iOS - copy 与 mutableCopy

    一说到拷贝,就不得不提浅拷贝和深拷贝。 何谓浅拷贝?何谓深拷贝? 往简单的说: 浅拷贝:拷贝地址。 深拷贝:拷贝内...

  • iOS面试题-第二页

    11.深拷贝和浅拷贝的理解. 深拷贝;拷贝的内容. 浅拷贝:拷贝的指针. 深拷贝如: NSMutableDicti...

  • js浅拷贝深拷贝

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

  • JS中的深拷贝与浅拷贝

    知乎:js中的深拷贝和浅拷贝? 掘金: js 深拷贝 vs 浅拷贝 前言 首先深拷贝与浅拷贝只针对 Object,...

  • iOS--拷贝相关题

    1、什么是深拷贝什么是浅拷贝?浅拷贝和深拷贝的区别 * 浅拷贝(shallow copy):指针拷贝,对于被拷贝对...

  • 2018-10-10day9函数基础

    1.浅拷贝、深拷贝 copy.copy(对象):浅拷贝copy.deepcopy(对象):深拷贝""" """拷贝...

  • 2018-10-10函数基础

    深拷贝和浅拷贝 深拷贝 copy.deepcopy(对象)浅拷贝 copy.copy(对象)深拷贝: 将对象对应的...

  • 深拷贝和浅拷贝

    1.深拷贝:地址的拷贝 2.浅拷贝:是值得拷贝 深拷贝和浅拷贝的区别 A拷贝B B变A变是浅拷贝 A拷贝B B变A...

  • 对象深拷贝和浅拷贝

    浅拷贝 深拷贝 深拷贝的递归方法 深拷贝的JSON方法

网友评论

      本文标题:深拷贝/浅拷贝

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