javascript深拷贝、浅拷贝梳理

xiaoxiao2021-02-28  59

前言

最近做项目时候,需要用到对象的深拷贝,图省事就直接上了JSON.parse(JSON.string(obj)),简单粗暴!!挺好用,但悲剧发生了,我的对象中有一个函数,然后这个方法就挂掉了,没法拷贝函数,只好就换了jq的$.extend()方法进行深拷贝。关于深拷贝、浅拷贝的问题,碰见过好多次,懒癌晚期的我每次都是临时抱佛脚,现查现用,终于今天再也忍不了了,系统整理下,做个记录

首先我们先了解一些javascript的基本知识

1、JavaScript变量包含两种不同类型的值:基本类型和引用类型。

    基本类型的值一共有6种:Undefined、Null、布尔值(Boolean)、字符串(String)、数值(Number)、Symbol(es6中新增)

    阴影类型值指那些可能由多个值构成的对象 只有一种:object

    在将一个值付给变量时,解析器必须确定这个值是基本类型值还是引用类型值。基本数据类型是按照值访问的,因此可以操作保存在变量中的实际值。而引用类型的值是保存在内存中的独享。JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象是,实际上是在操作对象的引用而不是实际的对象

2、JavaScript的变量储存方式--栈(stack)和堆(heap)

:自动分配内存空间,系统自动释放,里面存放的是基本类型的值和引用类型的地址

:动态分配内存,大小不定,也不会自动释放。里面存放引用类型的值

3、JavaScript值传递与址传递

值传递:基本类型采用的是值传递。

var a=1; var c=1; var b=a; b++; console.log(a)//1 console.log(b)//2 a===c //true

址传递:引用类型是地址传递,存放在栈内存的地址赋值给接受的变量。

var a=[1,2,3]; var c=[1,2,3,0]; var b=a; b.push(0); console.log(a)//[1,2,3,0] console.log(b)//[1,2,3,0] a===b//true a===c//false 内存地址不同

由于a和b都是引用类型,采用的是址传递,即a将地址传递给b,那么a和b必然指向同一个地址(引用类型的地址存放在栈内存中),而这个地址都指向了堆内存中引用类型的值。当b改变了这个值的同时,因为a的地址也指向了这个值,故a的值也跟着变化。

4、深复制和浅复制

所谓的浅复制,只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”。而深复制的话,我们要求复制一个复杂的对象,并且不会发生引用。

深复制和浅复制最根本的区别在于是否是真正获取了一个对象的复制实体(值),而不是引用

5、常见的深复制方法

1、jq的$.extend(true,obj1,obj2)第一个参数设置为true即可完成深度复制

2、JSON.parse(JSON.string(obj)) 此种方法复制对象 中 不能含有函数(貌似还有其他问题),

4、es6中的Object.assign({},obj) 此种方法只适用于根属性值都为基本类型的对象,局限性也很大(和Array.from()类似)

3、js递归实现

function deepCopy(p,c){ var i; c = c||{}; for(i in p){ if(p.hasOwnProperty(i)){ if(typeof(p[i])==="object"){ c[i] = Array.isArray(p[i])?[]:{}; deepCopy(p[i],c[i]); }else{ c[i] = p[i]; } } } return c; }

转载请注明原文地址: https://www.6miu.com/read-2632259.html

最新回复(0)