浅拷贝与深拷贝 如何实现一个深拷贝?

1.数据类型存储

基本数据类型保存在栈内存中

引用数据类型保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的引用,存在栈中

2.浅拷贝

浅拷贝,指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝

如果属性是基本数据类型,拷贝的就说基本类型的值,如果属性是引用类型,拷贝的就是内存地址

//封装一个函数进行浅拷贝
function shallowClone(obj) {
    //声明一个新的空对象存储拷贝后的数据
    const newObj = {}
    //遍历对象
    for(let key in obj) {
        //判断obj中是否有key属性
        if(obj.hasOwnProperty(key) ){
            //将数据克隆到新对象
            newObj[key] = obj[key]
        }
    }
    //返回值这个新对象    
    return newObj
}

hasOwnProperty(propertyName)

用来检测属性是否为对象自有属性 ,如果是则返回true,否则返回false,参数propertyName为要检测的属性名

hasOwnProperty() 方法是Object的原型方法(也称实例方法),它定义在Object.prototype对象之上,所有的Object的实例对象都可以继承hasOwnProperty()方法

hasOwnPorperty()只会检测对象自有的属性,不会检测对象原型上的属性,但是这些属性又是原型对象本身的自有属性,所以原型对象也可以使用hasOwnProperty()检测自己的自有属性

在JavaScript中,存在浅拷贝的现象有

(1)引用数据类型的直接赋值

(2)Object.assign()

用于将所有可枚举属性的值从一个或多个源对象复制到目标对象.它将返回目标对象

const target = {name:'张三',age:20}
const source = {sex :'男'}
const result = Object.assign(target,source)
console.log(target,target === result)//{name:'张三',age :20, sex:'男'} true

(3)Array.slice(start,end)

可以从已有的数组中返回某个选定的元素,可以提取字符串中的某个部分,并以新的字符串返回被提取的部分 

第一个参数 : start ,必须,规定从何处开始选取,如果该参数为负,则表示从原数组的倒数第集合元素开始提取

第二个参数 : end,可选.规定从何处结束提取,该参数是数组片段结束楚数组的下标,不写默认截取从start到数组结束的所有元素,如果为负数,则表示原数组中的倒数第几个元素结束抽取

返回值 : 返回一个新数组,包含从start(包含该元素)到end(不包括该元素)的元素

const obj = [
    {
        name: '张三',
        age: 20,
    },
    {
        name: '李四',
        age: 18
     }
]
const newObj = obj.slice(0)
obj[1].name = '小花'
console.log(obj, newObj)

slice仅仅拷贝了元素的地址

(4)Array.concat()

连接数组,返回值是连接后的数组

const arr = [
    {
        name : '熊大',
        age : 20,
    },
    {
        name : '熊二',
        age : 18,
    },
    {
        name : '光头强',
        age : 18,
    },

]
const newArr = arr.concat()
newArr[1].name = '吉吉国王'
console.log(arr,newArr)

​​​​​​​

 (5)展开运算符...

const arr = [
    {
        name : '佩奇',
        age : 18
    },
    {
        name : '乔治',
        age : 20
    },
]
const newArr = [...arr]  
newArr[1].name = '小花'
console.log(arr,newArr)

 ​​​​​​​​​​​​

 3.深拷贝

深拷贝开辟一个新的栈,两个对象完全相同,但是对应不同的地址,修改一个对象的属性,不会改变另一个对象的属性

常见的深拷贝方式有:

(1)_.cloneDeep()

const _ = require('lodash')
const obj1 = {
    a : 1,
    b : { f : { g : 1 } },
    c : [1,2,3]
}
const obj2 = _.cloneDeep(oobj1)
console.log(obj1.b.f === obj2.b.f)//false

(2).jQuery.extend()

const $ = require('jQuery')
const obj = {
    a : 1,
    b : { f : { g : 1 } },
    c : [ 1, 2, 3]
}
const obj2 = $.extend(true, {}, obj1}
consloe.log(obj1.b.f === obj2.b.f)//false
    

(3)JSON.stringify()

const obj2 = JSON.parse(JSON.stringify(obj1))

但是这种方式会存在弊端,会忽略undefined symbol 和函数

const obj = {
    name : 'a',
    name1 : undefined,
    name2 : function() {},
    name3 : Symbol('a')
}
const obj2 = JSON.parse(JSON.stringify(obj))
console.log(obj2)//{name:'a'}

 (4)循环递归

const obj = {
    name : '张三',
    age : 20,
    hobby : ['吃饭','睡觉','打豆豆'],
    students :{
        name : '小明',
        age : 18,
        course : 80
    }
}
//声明一个函数
function deepClone (obj,obj2){
    //遍历这个对象
    for(let key in obj){
        //如果对象包含数组
        if(obj[key] instanceof Array) {
            //则创建一个空数组
            obj2[key] = []
            //递归函数深拷贝数组
            deepClone(obj[key],obj2[key])
        }else if (obj[key] instanceof Object){//如果对象中包含对象
            //则创建一个空对象
            obj2[key] = {}
            //递归函数深拷贝对象
            deepClone(obj[key],obj2[key])
        }else {
            //如果是值类型就直接拷贝
            obj2[key] = obj[key]
        }       
    }
}
//开始拷贝
const obj2 = {}
deepClone(obj,obj2)
console.log(obj,obj2)

 4.区别

浅拷贝只拷贝属性指向某个对象的指针,而不是对象本身,修改拷贝后的数据,原数据也会修改

深拷贝则会创造一个一模一样的对象,新对象与原对象不共享内存,修改新对象的数据不会对原数据进行修改

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值