聊聊js的深拷贝和浅拷贝

一.深浅拷贝

...简单数据类型复杂数据类型

浅拷贝全部拷贝只拷贝第一层

深拷贝全部拷贝全部拷贝

二.刨根问底  为什么会出现深浅拷贝?

1.js数据底层存储原理

(1)基本数据类型: Number  String  Boolean  Null  Undifined

(2)复杂数据类型(包括但不限于): Object  Array Function  RegExp  Map

(3)栈存储: 存放简单数据类型的值和复杂数据类型在堆中的地址,存取顺序先进后出

(4)堆存储: 存放复杂数据类型的值;随机存,直接取

2.为什么在内存中:简单数据类型存放和复杂数据类型地址在栈中,复杂数据变量在堆中  这样存储?

(1)首先是堆比栈要大,但是栈比堆的运算速度要快。 (2)将复杂数据类型放在堆中的目的是为了不影响栈的效率,而是通过引用的方式去堆中查找。 (3)简单数据类型比较稳定,并且它只占据很小的内存,将它放在空间小、运算速度快的栈中,能够提高效率。                                     

三.刨根问底  底层是如何拷贝的?

下图告诉你:

let a = {

    name: '张三',

    children: {

          name: '大儿子',

          age: '18',

          eat: function () {

            console.log('大儿子:会吃')

          },

          sex: undefined,

          RegExp: /^[a-z0-9_-]{3,16}$/,

    },

    eat: function () {

      console.log('张三:会吃')

    },

    sex: undefined,

    RegExp: /^[a-z0-9_-]{3,16}$/,

}

let b={}

1.浅拷贝a,执行

b=a;

b在栈中申请空间,但是指向的是a在堆中地址,a变,则b变。

3.不完全的深拷贝a,执行

let b = Object.assign({}, a)

b的第一级,在堆中重新申请内存,但是二级三级还指向a的,不完全拷贝。

3.深拷贝a,执行

let b =lodash.deepClone(a)

b和a完全独立,b拷贝了a的所有层级,b不指向a的堆地址,而是对所有层级重新申请新的堆空间,存放自己得值。

四.什么开发场景下需要深拷贝?

1.我认知内的深拷贝开发场景

(1)如果拷贝一个级联地址,数据结构有三级:省市区,当我们进行数据拷贝的时候,浅拷贝只能拷贝第一级,并且如果拷贝数据值变了会影响到被拷贝值的值,那就会出现数据不一致。

比如:我的原数据A是:河北省 邯郸市 大名县,后来把A的值给B,那现在B的值就是:河北省邯郸市大名县,这个时候,改变A的值,A改成了:浙江省杭州市余杭区,那B的值会变成:浙江省邯郸市大名县,这个地址就错了,所以必须使用深拷贝。


综上所述:当拷贝变量是多层级的数据时,拷贝最好还是使用深拷贝。否则可能会导致数据错误。

五.实现深拷贝的几种常用方法及优缺点

1.不完全的深拷贝方式

(1)object.assign(a,b):

assign的用法

优点:可以拷贝函数;可以拷贝正则,可以拷贝undifined;

缺点:二级及以下不可以进行深拷贝。

(2)JSON.parse(JSON.stringify(a))

原理:将 JS 值转换为 JSON 字符串,然后将数据转换为 JS对象,相当于重新生成一个变量

JSON.stringify用法

JSON.parse用法

缺点:无法拷贝函数、正则、undifined。

优点:可以实现拷贝二级。

1.完全的深拷贝方式

(1)lodash递归

优点:可以实现完全拷贝且独立。

使用方法:

npm i --save lodash

import * as _ from 'lodash'

lodash.deepClone() // 深拷贝,完全

lodash使用方法

3.demo

let a = {

  name: '张三',

  children: {

    name: '大儿子',

    age: '18',

    eat: function () {

      console.log('大儿子:会吃')

    },

    sex: undefined,

    RegExp: /^[a-z0-9_-]{3,16}$/,

  },

  eat: function () {

    console.log('张三:会吃')

  },

  sex: undefined,

  RegExp: /^[a-z0-9_-]{3,16}$/,

}

// let b = a  // 赋值

// let b = Object.assign({}, a)  // 浅拷贝

// let b = JSON.parse(JSON.stringify(a)) // 深拷贝, 不完全

// lodash.deepClone() // 深拷贝,完全

a.name = '张四'

a.children.age = 100

console.log('a', a)

console.log('b', b)

扩展

jsonStringify 内存问题,研究一下

递归思想/算法

内存泄漏, 闭包,

  4. 节流 / 防抖

队列,数据列专题

Object.proxy()

你可能感兴趣的:(聊聊js的深拷贝和浅拷贝)