深拷贝和浅拷贝是javascript中一个比较复杂的问题,也是面试官最喜欢问的问题之一,通过这个为可以看出是否入门,深拷贝和浅拷贝也是初学者经常犯错一个点。

简单来说深拷贝是拷贝储存在栈中的对象,而浅拷贝是从内存中拷贝,这就涉及到数据存放位置了,总所周知,数据大体可以分为两种数据类型,一种是基本数据类型,数据结构不是很复杂,单独可以存在内存中就可以,而另一种是复杂数据类型,也叫引用数据类型,例如数组和对象,是放在栈中存储的,而基本数据类型是放在内存中的,不涉及深拷贝和浅拷贝,也可以说基本数据类型都是深拷贝

而引用类型数据存储比较复杂,例如var a=[1,3,4]  这句话的存储就是首先在内存开辟一个空间,但是内存当中不可以存储这种复杂数据类型,所以要把这种结构放到栈当中,栈相当于一个密码箱,而钥匙存在内存当中,这就构成了一个存储关系,浅拷贝var b=a简单来说就是把这份钥匙复制了一份,但内存当中的数据并没有复制,所以如果改变a相应b也会改变

而深拷贝则需要在栈中在生成一个密码箱,生成一把新钥匙(钥匙2),这样深拷贝的两种数值不会相互影响,也可以说没有任何关系了

方法:

1:jq使用,$.extend({},obj)

2:Object.assign({},obj)

这两种比较基础,估计都会使用

3:clone(obj)

var clone = function (obj) { return JSON.parse(JSON.stringify(obj)); }
这种方法有种缺陷,这种方法会忽略值为function以及undefied的字段,而且对date类型的支持也不太友好。

4:clone(obj)

var clone = function (obj) {
if(obj === null) return null
if(typeof obj !== 'object') return obj;
if(obj.constructor===Date) return new Date(obj);
var newObj = new obj.constructor (); //保持继承链
for (var key in obj) {
if (obj.hasOwnProperty(key)) { //不遍历其原型链上的属性
var val = obj[key];
newObj[key] = typeof val === 'object' ? arguments.callee(val) : val; // 使用arguments.callee解除与函数名的耦合
}
}
return newObj;
};
这种方法也就使封装最好的深拷贝的方法,以下为解释:

1、用new obj.constructor ()构造函数新建一个空的对象,而不是使用{}或者[],这样可以保持原形链的继承;
2、用obj.hasOwnProperty(key)来判断属性是否来自原型链上,因为for..in..也会遍历其原型链上的可枚举属性。
3、上面的函数用到递归算法,在函数有名字,而且名字以后也不会变的情况下,这样定义没有问题。但问题是这个函数的执行与函数名 factorial 紧紧耦合在了一起。为了消除这种紧密耦合的现象,需要使用 arguments.callee。
---------------------
作者:zuggs_
来源:CSDN
原文:https://blog.csdn.net/zuggs_/article/details/84784933
版权声明:本文为博主原创文章,转载请附上博文链接!

js对象的深拷贝及其的几种方法的更多相关文章

  1. js对象之间的"继承"的五种方法

    今天要介绍的是,对象之间的"继承"的五种方法. 比如,现在有一个"动物"对象的构造函数. function Animal(){ this.species = & ...

  2. JavaScript进阶(四)js字符串转换成数字的三种方法

    js字符串转换成数字的三种方法 在js读取文本框或者其它表单数据的时候获得的值是字符串类型的,例如两个文本框a和b,如果获得a的value值为11,b的value值为9 ,那么a.value要小于b. ...

  3. Jsp页面跳转和js控制页面跳转的几种方法

    Jsp 页面跳转的几种方法 1. RequestDispatcher.forward() 在服务器端起作用,当使用forward()时,Servlet engine传递HTTP请求从当前的Servle ...

  4. js 动态加载事件的几种方法总结

    本篇文章主要是对js 动态加载事件的几种方法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助   有些时候需要动态加载javascript事件的一些方法往往我们需要在 JS 中动态添 ...

  5. js如何动态创建表格(两种方法)

    js如何动态创建表格(两种方法) 一.总结 一句话总结: 1.方法一:写好创建表格的html代码,将之赋值给div的innerHTML. 2.方法二.直接用创建好的table元素的方法insertRo ...

  6. js中常用追加元素的几种方法

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. javascript获取json对象的key名称的两种方法

    javascript获取json对象的key名称的两种方法 数据处理中,你可能接收到一个不确定内容格式的json对象,然后要把key的值提取出来.今天试过两种可以提取json key的方法,均可以正常 ...

  8. 原生JS—实现图片循环切换的两种方法

    今天我们主要讲讲如何使用原生JS实现图片的循环切换的方法.多余的话我们就不多说了,我们一个一个开始讲吧. 1  原生JS实现图片循环切换 -- 方法一 在上栗子之前我们先简单介绍一下所用的一些知识点. ...

  9. js 控制页面跳转的5种方法

    js 控制页面跳转的5种方法 编程式导航: 点击跳转路由,称编程式导航,用js编写代码跳转. History是bom中的 History.back是回退一页 Histiory.go(1)前进一页 Hi ...

随机推荐

  1. web端常见测试

    一.登录注册功能 1.页面调转 2.tab键与enter键 3.密码加密显示,是否支持复制粘贴 4.账号密码校验 5.刷新页面,更新验证码 二.界面测试 1.样式.颜色.整体布局风格 2.最大化.最小 ...

  2. codechef Chef and The Colored Grid

    难度 \(hard\) 题意 \(3\times n\)的方格,前两行已分别填入\(n-\)排列,要求求第三行填入\(n-\)排列,使得每行每列数不重复的方案数(数据保证前两行合法)\(n\le 10 ...

  3. C# ASCII码的转换、转义字符、对照表

    var splitStr = new byte[] { 0x05, 0x0D, 0x0A };//var splitStr = new byte[] { 5, 13, 10 };这样写也可以 var ...

  4. 01、学习c++必知的几个网站

    1.https://zh.cppreference.com/ 2.http://www.cplusplus.com/ 3.https://gcc.gnu.org/onlinedocs/libstdc+ ...

  5. 题解 AT3717 【[ABC081A] Placing Marbles】

    题目传送门. 分析 我们可以把字符串中所有数加起来输出,那么到底怎么把一个字符变成一个数字呢.我们只需要减去字符\(0\)就可以了. 详细步骤 定义字符串\(s\)并将其输入. string s; c ...

  6. Log4net实用说明

    Log4net实用说明 Appender Filter Layout Logger ObjectRender Repository PatterLayout格式化字符表 配置文件说明 Appender ...

  7. php 文件追加写入

    //追加写入 file_put_contents('xml.text',json_encode($postObj,JSON_FORCE_OBJECT).PHP_EOL,FILE_APPEND);

  8. 洛谷P1551 亲戚 (并查集模板题)

    链接 https://www.luogu.org/problemnew/show/P1551 代码 #include<bits/stdc++.h> using namespace std; ...

  9. 《深入理解java虚拟机》读书笔记三——第四章

    第四章 虚拟机性能监控与故障处理工具 1.JDK命令行工具 jps命令: 作用:列出正在运行的虚拟机进程. 格式:jps [option] [hostid] 选项:-q 只输出LVMID(Local ...

  10. Ubuntu16.04突然断网

    配置文件: sudo gedit /etc/network/interfaces 重启网络: 1.sudo /etc/init.d/networking restart 2.sudo service ...