JavaScript的深拷贝和浅拷贝

原文

  简书原文:https://www.jianshu.com/p/3d930756dd8f

大纲

  前言
  1、对深拷贝和浅拷贝的初步认识
  2、深拷贝和浅拷贝的区别
  3、浅拷贝存在的缺陷
  4、深拷贝的实现方式

前言

  对于很多初次接触JavaScript的读者来说,想要实现对象的拷贝/复制,就是单纯的使用赋值语句(=)来实现需求。但是,这样的方式是不全面的,这样的方法对于简单类型的数据来说是没有问题的,但是如果是对于像对象这样的复杂的数据类型来说,这样的实现方式有就会给你带来意想不到的问题。那么,如果不能简单的用赋值语句实现对象的拷贝(复制),我们应该用什么样的方式呢?这个,就是深拷贝和浅拷贝的意义所在了。

1、对深拷贝和浅拷贝的初步认识

  深拷贝和浅拷贝只针对像 Object, Array 这样的复杂对象的。简单来说,浅拷贝只拷贝一层对象的属性,而深拷贝则递归拷贝了所有层级。
  对于字符串类型,浅拷贝是对值的复制,对于对象来说,浅拷贝是对对象地址的复制,并没有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变,而深拷贝则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。

2、深拷贝和浅拷贝的区别

  虽然两者都是对内容的拷贝,但是拷贝的内容的不同是区分两者的关键,而这个不同主要体现在对Object和Array这样的复杂对象。最直接的原因是诸如字符串这样简单的类型的拷贝就是内容的复制,并不会有别的什么深层次的东西,但是对于Objcet和Array这样复杂的类型,主要是由于对象的复制是基于对对象的地址的复制而不是整体内容的复制(对象包含了key ,value)。
  简而言之:浅拷贝之后的对象实际上都是同一个对象,而深拷贝之后的对象都是除了内容相同以外完全无关的对象。

3、浅拷贝存在的缺陷

  通过一个实例来说明使用浅拷贝对对象进行复制会导致哪些问题,从而正确认识使用深拷贝和浅拷贝的重要意义。

var obj = { a:1, arr: [2,3] };
var shallowObj = shallowCopy(obj);

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

/*
    导致的结果就是:
        对shallowObj对象的更改也会影响到原对象obj,即所谓的牵一发而动全身。
*/
shallowObj.arr[1] = 5;
obj.arr[1]   // = 5

4、深拷贝的实现方式

  以下介绍两种我平时收集到并且常用的深拷贝的实现方式,希望能对读者有所帮助。

4.1、通过JSON解析解决

  针对纯 JSON 数据对象的深复制,使用 JSON 全局对象的 parse 和 stringify 方法来实现深复制也算是一个简单讨巧的方法。然而使用这种方法会有一些隐藏的坑,它能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。

var test = {
    person: {
        name: {
            first: ‘chen‘,
            last: ‘kk‘
        },
        age: 12
    },
    interest: [‘book‘, ‘run‘, ‘jump‘]
}
var result = JSON.parse(JSON.stringify(test))
result.interest.push(‘sing‘)
console.dir(test)//[‘book‘, ‘run‘, ‘jump‘]
console.dir(result)//friend: [‘book‘, ‘run‘, ‘jump‘,‘sing‘]

4.2、通过递归解析解决

  想要获得多层的数据结构的数据的深拷贝,不得不考虑使用迭代的方式。下列的方法将需要考虑深拷贝的对象、Array数据类型,并不断的通过迭代判断来对这两种类型的数据进行深拷贝。

var china = {
    nation: ‘中国‘,
    birthplaces: [‘北京‘, ‘上海‘, ‘广州‘],
    skincolr: ‘yellow‘,
    friends: [‘sk‘, ‘ls‘]
}
//深复制,要想达到深复制就需要用递归
function deepCopy(o, c) {
    var c = c || {}
    for (var i in o) {
        if (typeof o[i] === ‘object‘) {
            //要考虑深复制问题了
            if (o[i].constructor === Array) {
                //这是数组
                c[i] = []
            } else {
                //这是对象
                c[i] = {}
            }
            deepCopy(o[i], c[i])
        } else {
            c[i] = o[i]
        }
    }
    return c
}
var result = {
    name: ‘result‘
}
result = deepCopy(china, result)
console.dir(result)

  

原文地址:https://www.cnblogs.com/shcrk/p/9261074.html

时间: 2024-10-05 23:09:26

JavaScript的深拷贝和浅拷贝的相关文章

javaScript之深拷贝与浅拷贝

js中有两种数据类型: 1.  基本类型  :  Number.String.Boolean.Null.Undefined 2.  复杂类型  :  Object .Array 深拷贝和浅拷贝只针对复杂类型的数据,因为基本类型数据的定义都会重新开辟新的内存. 浅拷贝拷贝的是内存地址,只是增加一个指针指向已有的内存,这时多个数据共用一个内存空间:深拷贝是新增了指针并且新开辟了内存空间,新指针指向新的内存. 浅拷贝: var a={ name:'WangJing', sex:'女', age:'25

Javascript学习之深拷贝和浅拷贝详解

在JavaScript 中,存在着这样的两种拷贝方式.分别是:深拷贝和浅拷贝,这两种拷贝在实际中非常的常见,如果读者是一个阅读源码的爱好者,相信多多少少对深拷贝和浅拷贝有所了解.本文和大家分享的就是深拷贝和浅拷贝相关内容,一起来看看吧,希望对大家 学习javascript有所帮助. 一.浅拷贝 浅拷贝在现实中最常见的表现在赋值上面,例如 <!DOCTYPE html> <html lang="en"> <head> <meta charset=

Javascript中的深拷贝和浅拷贝

文章目录 JavaScript中的变量类型 深拷贝和浅拷贝的理解 深拷贝和浅拷贝的实现方式 为什么需要深拷贝和浅拷贝 JavaScript中的变量类型 (1).基本类型 JavaScript中的基本类型有五种: null.undefined.boolean.string.number. 变量是按值存放的,存放在栈中的简单数据段,可以直接访问. (2).引用类型 引用类型包括对象和数组,其存储在堆当中,而变量是指针,指向堆. 当我们访问的时候,实际上是访问指针,然后指针去寻找对象或数组. 深拷贝与

深入剖析javaScript中的深拷贝和浅拷贝

在面试时经常会碰到面试官问:什么是深拷贝和浅拷贝,请举例说明?如何区分深拷贝与浅拷贝,简单来说,假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,如果B没变,那就是深拷贝:我们先看两个简单的案例: //案例1(深拷贝) var a1 = 1, a2= a1; console.log(a1) //1 console.log(a2) //1 a2 = 2; //修改 a2 console.log(a1) //1 console.log(a2) //2 //案例2(浅拷

JavaScript中面向对象的的深拷贝和浅拷贝

理解深拷贝和浅拷贝之前需要弄懂一些基础概念,内存中存储的变量类型分为值类型和引用类型. 1.值类型赋值的存储特点, 将变量内的数据全部拷贝一份, 存储给新的变量. 例如:var num = 123 :var num1=num; 表示变量中存储的数字是 123.然后将数据拷贝一份,就是将 123 拷贝一份. 那么内存中有 2 个 数组;将拷贝数据赋值给 num2,其特点是在内存中有两个数据副本.这可以理解为浅拷贝. 2.引用类型的赋值. var o={name:'张三‘}: var obj=o;

javascript实现引用数据类型的深拷贝和浅拷贝详解

关于引用类型值的详解,请看另一篇随笔 https://www.cnblogs.com/jinbang/p/10346584.html 深拷贝和浅拷贝,也就是引用数据类型栈和堆的知识点.深浅拷贝的原型都是Object,深拷贝指向的栈内存不一样,浅拷贝指向的栈内存一样): 如何区分深拷贝与浅拷贝,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B没有发生变化,说明是深拷贝.如果B也跟着发生了变化,说明是浅拷贝. let obj = { name: "jin", arr: [&quo

js的命名空间 &amp;&amp; 单体模式 &amp;&amp; 变量深拷贝和浅拷贝 &amp;&amp; 页面弹窗设计

说在前面:这是我近期开发或者看书遇到的一些点,觉得还是蛮重要的. 一.为你的 JavaScript 对象提供命名空间 <!DOCTYPE html> <html> <head> <title>为自己的js对象提供命名空间</title> </head> <body> <div>封装自己的数据和函数,防止和其他的库搞混了</div> <script> var jscbObject = {

【JS】深拷贝与浅拷贝的区别,实现深拷贝的几种方法

如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果A没变,那就是深拷贝,自食其力. 此篇文章中也会简单阐述到栈堆,基本数据类型与引用数据类型,因为这些概念能更好的让你理解深拷贝与浅拷贝. 我们来举个浅拷贝例子: let a=[0,1,2,3,4], b=a; console.log(a===b); a[0]=1; console.log(a,b); 嗯?明明b复制了a,为啥修改数组a,数组b也跟着变了,这里我不

深拷贝与浅拷贝js,方法

在使用JavaScript对数组进行操作的时候,我们经常需要将数组进行备份,事实证明如果只是简单的将它赋予其他变量,那么我们只要更改其中的任何一个,然后其他的也会跟着改变,这就导致了问题的发生. 参考Object.assign():https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign <!DOCTYPE html> <html> <head&