IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 师妹又问JavaScript中数据的深浅拷贝方法,这次给她安排上咯! -> 正文阅读

[JavaScript知识库]师妹又问JavaScript中数据的深浅拷贝方法,这次给她安排上咯!

JavaScript中数据的深浅拷贝

师妹啊,咱们在讲深浅拷贝之前我们先要明白javascript中数据的赋值是如何存储的,接下来再介绍深浅拷贝的方法,看好哦。

赋值:简单数据类型直接在栈中开辟一块新的内存,存储赋值的数据;引用数据类型,在栈中开辟一块空间,存储赋值的数据对应的堆中的存储地址,源数据和拷贝的新数据对应的是同一块堆空间中的数据

浅拷贝:堆栈各开辟一块新空间,栈中存储堆中新开辟的空间的地址,堆中赋值了源数据的数据,如果值是基本数据类型那么新数据和源数据没有任何关系,如果值是引用数据类型那么新数据的值指向的源数据的数据存储地址

深拷贝:堆栈各开辟一块新空间,栈中存储堆中新开辟的空间的地址,堆中存储的数据和源数据一样,但是二者没有任何联系

浅拷贝方法

1.Object.assign()

Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。

let obj1 = {
    person: {
        name: 'zs',
        age: 19
    },
    play: 'football'
}

let obj2 = Object.assign(obj1)
obj1.person.name = 'ls'
console.log(obj2)   //{ person: { name: 'ls', age: 19 }, play: 'football' }
2.函数库lodash的_.clone方法

该函数库也有提供_.clone用来做 Shallow Copy,后面我们会介绍利用这个库实现深拷贝。

let _ = require('lodash')

let obj1 = {
    person: {
        name: 'zs',
        age: 19
    },
    play: 'football'
}

let obj2 = _.clone(obj1)
obj1.person.name = 'ls'

console.log(obj2)  //{ person: { name: 'ls', age: 19 }, play: 'football' }
3.展开运算符…

展开运算符是一个 es6 / es2015特性,它提供了一种非常方便的方式来执行浅拷贝,这与 Object.assign ()的功能相同。

let obj1 = { name: 'zs', address: { x: 100, y: 100 } }
let obj2 = { ...obj1 }
obj1.address.x = 200;
obj1.name = 'lisi'
console.log('obj2', obj2)   //obj2 { name: 'zs', address: { x: 200, y: 100 } }
4.Array.prototype.concat()
let arr1 = [123, 'jh', {
    name: 'zs',
    age: 19
}]

let arr2 = arr1.concat()
arr1[1] = 'asf'
arr1[2].age = 20
console.log(arr2)  //[ 123, 'jh', { name: 'zs', age: 20 } ]
5.Array.prototype.slice()
let arr1 = [123, 'jh', {
    name: 'zs',
    age: 19
}]

let arr2 = arr1.slice()
arr1[1] = 'asf'
arr1[2].age = 20
console.log(arr2) //[ 123, 'jh', { name: 'zs', age: 20 } ]

深拷贝方法

1.JSON.parse(JSON.stringify())

利用JSON.stringify将对象转成JSON字符串,再用JSON.parse把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。

let arr = [1, 3, {
    username: 'agul'
}];
let arr1 = JSON.parse(JSON.stringify(arr))
arr[2].username = 'pjh';
console.log(arr, arr1)  // [ 1, 3, { username: 'pjh' } ] [ 1, 3, { username: 'agul' } ]
let obj1 = {
    a: 1,
    b: { f: { g: 1 } }
}
let obj2 = JSON.parse(JSON.stringify(obj1))
obj1.b.f.g = 2
console.log(obj1, obj2) //{ a: 1, b: { f: { g: 2 } } } { a: 1, b: { f: { g: 1 } } }
//可以实现数组或对象深拷贝,但不能处理函数和正则
2.函数库lodash的_.cloneDeep方法

该函数库也有提供_.cloneDeep用来做 Deep Copy

let _ = require('lodash')
let obj1 = {
    a: 1,
    b: { f: { g: 1 } }
}

let obj2 = _.cloneDeep(obj1)
console.log(obj1.b === obj2.b) //false
console.log(obj1 === obj2) // false
3.jQuery.extend()方法

jquery 有提供一個$.extend可以用来做 Deep Copy

// $.extend(deepCopy, target, object1, [objectN])//第一个参数为true,就是深拷贝
var $ = require('jquery');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = $.extend(true, {}, obj1);
console.log(obj1.b.f === obj2.b.f); // false
4.手写递归方法

递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝

有种特殊情况需注意就是对象存在循环引用的情况,即对象的属性直接的引用了自身的情况,解决循环引用问题,我们可以额外开辟一个存储空间,来存储当前对象和拷贝对象的对应关系,当需要拷贝当前对象时,先去存储空间中找,有没有拷贝过这个对象,如果有的话直接返回,如果没有的话继续拷贝,这样就巧妙化解的循环引用的问题。

function deepClone(obj, hash = new WeakMap) {
    if (obj === null) return obj;
    if (obj instanceof Date) return new Date(obj);
    if (obj instanceof RegExp) return new RegExp(obj);
    if (typeof obj !== 'object') return obj; // 除了对象外直接拷贝
    if (hash.get(obj)) return hash.get(obj); // 将引用存储起来,避免循环引用,存在则不再拷贝
    let cloneObj = new obj.constructor();    // 原型的constructor指向当前类本身
    hash.set(obj, cloneObj);
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            cloneObj[key] = deepClone(obj[key], hash);
        }
    }
    return cloneObj
}

let obj = { name: 'zs', age: 18, address: { short: 'guangdong' } }
obj.o = obj  // 对象存在循环引用的情况
let obj2 = deepClone(obj)
obj.address.short = 'beijing'
console.log(obj2)

循环引用

当对象 1 中的某个属性指向对象 2,对象 2 中的某个属性指向对象 1 就会出现循环引用,(当然不止这一种情况,不过原理是一样的)

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-16 11:11:21  更:2021-07-16 11:11:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 7:02:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码