关于引用类型值的详解,请看另一篇随笔 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. hihoCoder#1062 最近公共祖先·

    原题地址 A和A的共同祖先是A,即使A没有在之前的家谱中出现过!被这个坑了,WA了很久... 比如:小头爸爸是大头儿子他爹,问:隔壁王叔叔和隔壁王叔叔的最近祖先是谁?,答:隔壁王叔叔. 代码: #in ...

  2. [luoguP2617] Dynamic Ranking(树状数组 套 主席树 + 离散化)

    传送门 BZOJ上是权限题,洛谷赞啊. 求区间 K 大数很简单. 但是如果修改某个数的话,那么就得把这个数及后面所建的主席树都更新一遍 nlogn,显然不行. 所以可以在外面套一个树状数组来优化,树状 ...

  3. Codeforces Round #259 (Div. 2) D

    D. Little Pony and Harmony Chest time limit per test 4 seconds memory limit per test 256 megabytes i ...

  4. android源码mm时的编译错误no ruler to make target `out/target/common/obj/JAVA_LIBRARIES/xxxx/javalib.jar', needed by `out/target/common/obj/APPS/xxxx_intermediates/classes-full-debug.jar'. Stop.

    瞧见没有,就因为多了这一个反斜杠,浪费了一下午时间找问题,哭了~~~~

  5. Uva -1515 Pool construction(最小割)

    输入一个字符矩阵,'.'代表洞,'#'代表草地.可以把草改成洞花费为d,或者把洞改成草花费为f,最后还要在草和洞之间修围栏花费为b. 首先把最外一圈的洞变成草,并累加花费. 增加一个源点和一个汇点,源 ...

  6. 链表倒置,这个还是考验仔细程度,第一遍还没做对 —— 剑指Offer

    https://www.nowcoder.net/practice/75e878df47f24fdc9dc3e400ec6058ca?tpId=13&tqId=11168&tPage= ...

  7. 踩坑录-IDEA编辑器:找不到TomcatService或ApplicationServers----TomcatService使用指南

    一.找不到TomcatService或ApplicationServers Setp1. 检查IDEA版本 检查IDEA版本是否为Ultimate(终极版需要激活),Community(社区版免费无需 ...

  8. Sockets Tutorial

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

  9. win7开启超级管理员账户(Administrator)

    win7开启超级管理员账户(Administrator) 不同于XP系统,Windows7系统据说出于安全的考虑,将超级管理员帐户"Administrator"在登陆界面给隐藏了, ...

  10. [Spring] Bean Scope Singleton cs Prototype

    We can define a class to be Singleton or Prototype. If the class was defined as Prototype, then ever ...