关于引用类型值的详解,请看另一篇随笔 https://www.cnblogs.com/jinbang/p/10346584.html

深拷贝和浅拷贝,也就是引用数据类型栈和堆的知识点。深浅拷贝的原型都是Object,深拷贝指向的堆内存不一样,浅拷贝指向的堆内存一样):
如何区分深拷贝与浅拷贝,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B没有发生变化,说明是深拷贝。如果B也跟着发生了变化,说明是浅拷贝。
      let obj = { name: "jin", arr: ["red","blue","black"]};
let obj1 = {};
Object.defineProperties(obj1, Object.getOwnPropertyDescriptors(obj)); // 深拷贝
Object.assign(obj1, obj); // 深拷贝
obj1 = JSON.parse(JSON.stringify(obj)); // 深拷贝
obj1 = deepCopy(obj); // 使用到深拷贝函数
obj1 = obj; // 浅拷贝
obj1 = Object.assign(obj); // 浅拷贝

下面是deepCopy()深拷贝函数,其中使用到了判断变量的类型函数

      // 判断变量的类型
function getType(obj){
let str = Object.prototype.toString.call(obj); // 检测基本类型值,引用类型值的类型
let map = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'unfefined',
'[object Null]': 'null',
'[object Object]': 'object'
};
if(obj instanceof Element){
return 'element';
}
return map[str];
} // 深拷贝函数
function deepCopy(p){
let obj;
let str = getType(p);
if(str === 'array'){
obj = [];
for(let i=0;i<p.length;i++){
// obj.push(p[i]); // 不能这样写,因为会把array的堆内存也会复制过去
obj.push(arguments.callee(p[i])); //回调自己
}
}else if(str === 'object'){
obj = {};
for(let i in p){
// obj[i] = p[i]; // 不能这样写,因为会把object的堆内存也会复制过去
obj[i] = arguments.callee(p[i]); //回调自己
}
} else {
return p;
}
return obj;
}

需要特别注意的是,使用JSON.parse(JSON.stringify(x))不是一个很好的选择,也算是它们的坑吧:

对象是由构造函数生成的:会丢弃对象的constructor,因为JSON.stringify()只能序列化对象的可枚举的自有属性
时间对象:变成字符串
RegExp,Error对象:变成空对象
函数,undefined:会被丢失
NaN,Infinity和-Infinity:变成null
function Person(name){
this.name = name;
}
var person = new Person('liai'); var test = {
name: 'jin',
person: person, //对象是由构造函数生成的:会丢弃对象的constructor
date: new Date(), //序列化后返回是字符串,不是时间对象
regexp: new RegExp('\\w+'), //序列化后返回空对象:{}
err: new Error(), //序列化后返回空对象:{}
fun: function(){}, //序列化后会丢失
undef: undefined, //序列化后会丢失
nun: NaN, //序列化后返回null
};
console.log(test);
console.log(JSON.parse(JSON.stringify(test)));

javascript实现引用数据类型的深拷贝和浅拷贝详解的更多相关文章

  1. 【转】 c++拷贝构造函数(深拷贝,浅拷贝)详解

     c++拷贝构造函数(深拷贝,浅拷贝)详解 2013-11-05 20:30:29 分类: C/C++ 原文地址:http://blog.chinaunix.net/uid-28977986-id-3 ...

  2. 【C++】拷贝构造函数(深拷贝,浅拷贝)详解

    一.什么是拷贝构造函数  首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: ; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量. 下面看一个类对 ...

  3. **Python中的深拷贝和浅拷贝详解

    Python中的深拷贝和浅拷贝详解   这篇文章主要介绍了Python中的深拷贝和浅拷贝详解,本文讲解了变量-对象-引用.可变对象-不可变对象.拷贝等内容.   要说清楚Python中的深浅拷贝,需要 ...

  4. c++拷贝构造函数(深拷贝,浅拷贝)详解

    一.什么是拷贝构造函数      首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: ; int b=a;   而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.  下面 ...

  5. OC细节 - 1.深拷贝与浅拷贝详解

    概述 拷贝:复制一个与源对象内容相同的对象 实现拷贝,需要遵守以下两个协议 NSCopying NSMutableCopying 拷贝返回对象的种类 可变,mutableCopy消息返回的对象 不可变 ...

  6. python的拷贝方式以及深拷贝,浅拷贝详解

    python的拷贝方法有:切片方法, 工厂方法, 深拷贝方法, 浅拷贝方法等. 几种方法都可以实现拷贝操作, 具体区别在于两点:1.代码写法不同. 2.内存地址引用不同 代码演示: import co ...

  7. C++ 深拷贝和浅拷贝详解

    前言 在对象拷贝过程中,如果没有自定义拷贝构造函数,系统会提供一个缺省的拷贝构造函数,缺省的拷贝构造函数对于基本类型的成员变量,按字节复制,对于类类型成员变量,调用其相应类型的拷贝构造函数. 位拷贝( ...

  8. GoLang基础数据类型--->字典(map)详解

    GoLang基础数据类型--->字典(map)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   可能大家刚刚接触Golang的小伙伴都会跟我一样,这个map是干嘛的,是 ...

  9. GoLang基础数据类型-切片(slice)详解

    GoLang基础数据类型-切片(slice)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 数组的长度在定义之后无法再次修改:数组是值类型,每次传递都将产生一份副本.显然这种数 ...

随机推荐

  1. 整体二分--BZOJ1901: Zju2112 Dynamic Rankings

    n<=10000个数有m<=10000个操作,1.询问一个区间的第k小的数:2.单点修改. 带修主席树. 整体二分. 整体二分的必要条件: #include<string.h> ...

  2. 从零开始写STL-内存部分-内存分配器allocator

    从零开始写STL-内存部分-内存分配器allocator 内存分配器是什么? 一般而言,c++的内存分配和释放是这样操作的 >>class Foo{ //...}; >>Foo ...

  3. POJ 3469_Dual Core CPU

    题意: N个模块可以在A,B两个核上运行,分别需要A[i]和B[i],模块之间需要传递数据,若两个模块在同一核上,则不需要花费,否则需要花费w[i].问最少需要花费多少? 分析: 用最小的费用将两个对 ...

  4. [bzoj1485][HNOI2009]有趣的数列_卡特兰数_组合数

    有趣的数列 bzoj-1485 HNOI-2009 题目大意:求所有1~2n的排列满足奇数项递增,偶数项递增.相邻奇数项大于偶数项的序列个数%P. 注释:$1\le n\le 10^6$,$1\le ...

  5. FJNUOJ1158(莫比乌斯反演)

    题目:给定n个数字a1...an.有m个询问,格式为L R X Y,意为求aL到aR之间与x的最大公因数为y的个数. 数据组数T<=20 1<=n,m<=1e5 1<=ai&l ...

  6. 03-js变量强制转换

    <html> <head> <title>js中的变量强转</title> <meta charset="UTF-8"/> ...

  7. 对于事务ACID的理解

    ACID,即以下四点: 原子性(Atomicity) 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生. 一致性(Consistency) 事务前后数据的完整性必须保持一致 ...

  8. Mybatis中的ognl表达式。及myabtis where标签/if test标签/trim标签

    1.mybatis默认支持使用ognl表达式来生成动态sql语句 MyBatis中可以使用OGNL的地方有两处: 动态SQL表达式中 ${param}参数中 上面这两处地方在MyBatis中处理的时候 ...

  9. Sockets Tutorial

    Sockets Tutorial This is a simple tutorial on using sockets for interprocess communication. The clie ...

  10. Word Break II 求把字符串拆分为字典里的单词的全部方案 @LeetCode

    这道题相似  Word Break 推断能否把字符串拆分为字典里的单词 @LeetCode 只不过要求计算的并不不过能否拆分,而是要求出全部的拆分方案. 因此用递归. 可是直接递归做会超时,原因是Le ...