javascript对浅拷贝和深拷贝的详解


Posted in Javascript onOctober 14, 2016

下面小编就为大家带来一篇浅谈JavaScript中面向对象的的深拷贝和浅拷贝。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。

1.浅拷贝:复制一份引用,所有引用对象都指向一份数据,并且都可以修改这份数据。

2.深拷贝(复杂):复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。

这里画一个简单的图来加深理解:

javascript对浅拷贝和深拷贝的详解

一、数组的深浅拷贝

在使用JavaScript对数组进行操作的时候,我们经常需要将数组进行备份,事实证明如果只是简单的将它赋予其他变量,那么我们只要更改其中的任何一个,然后其他的也会跟着改变,这就导致了问题的发生。

var arr = ["One","Two","Three"];
var arrto = arr;
arrto[1] = "test";
document.writeln("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,test,Three
document.writeln("数组的新值:" + arrto + "<br />");//Export:数组的新值:One,test,Three

像上面的这种直接赋值的方式就是浅拷贝,很多时候,这样并不是我们想要得到的结果,其实我们想要的是arr的值不变,不是吗?

方法一:js的slice函数

var arr = ["One","Two","Three"];
var arrtoo = arr.slice(0);
arrtoo[1] = "set Map";
document.writeln("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,Two,Three
document.writeln("数组的新值:" + arrtoo + "<br />");//Export:数组的新值:One,set Map,Three

方法二:js的concat方法

var arr = ["One","Two","Three"];
var arrtooo = arr.concat();
arrtooo[1] = "set Map To";
document.writeln("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,Two,Three
document.writeln("数组的新值:" + arrtooo + "<br />");//Export:数组的新值:One,set Map To,Three

二、对象的深浅拷贝

var a={name:'yy',age:26};
var b=new Object();
b.name=a.name;
b.age=a.age;
a.name='xx';
console.log(b);//Object { name="yy", age=26}
console.log(a);//Object { name="xx", age=26}

就是把对象的属性遍历一遍,赋给一个新的对象。

var deepCopy= function(source) { 
var result={};
for (var key in source) {
 result[key] = typeof source[key]==='object'? deepCoyp(source[key]): source[key];
 } 
 return result; 
}

举一个jQuery中的例子:

jQuery.extend = jQuery.fn.extend = function() {//1.将extend方法扩展到JQ(函数)下边:扩展静态方法
 //2. jQuery.fn.extend 把extend扩展到jq.fn下 且jQuery.fn = jQuery.prototype 扩展实例方法
 // 1.2.功能相似
 var options, name, src, copy, copyIsArray, clone, //定义一些变量
 target = arguments[0] || {}, 
 //目标元素是【0】第一个元素$.extend( a , { name : 'hello' } , { age : 30 } );
 i = 1, //第一个元素的位置
 length = arguments.length,//第一个个对象的元素
 deep = false; //是否是深拷贝 默认 false不是

 // Handle a deep copy situation 看是不是深拷贝情况
 if ( typeof target === "boolean" ) { //是布尔值 
 deep = target;
 target = arguments[1] || {}; //目标元素是第二个$.extend( true , a , b )
 // skip the boolean and the target
 i = 2;
 }

 // Handle case when target is a string or something (possible in deep copy) 看参数正确不
 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
 // 当目标不是对象或者不是函数的时候
 target = {}; //变成一个空的jason
 }

 // extend jQuery itself if only one argument is passed看是不是插件情况
 if ( length === i ) { //只写了一个对象 要把这个对象扩展到jq源码上 静态方法 或者是实例方法
 target = this; //this 是$ 或者 $();
 --i;
 }
// 可能有多个对象情况
 for ( ; i < length; i++ ) {
 // Only deal with non-null/undefined values
 if ( (options = arguments[ i ]) != null ) {//看后边的对象是否都有值
 // Extend the base object
 for ( name in options ) {
 src = target[ name ];
 copy = options[ name ];

 // Prevent never-ending loop
 if ( target === copy ) {//防止循环引用 
  continue;//跳出本次循环继续执行
  // $.extend( a , { name : a } ) );循环引用 a也是一个对象
 }

 // Recurse if we're merging plain objects or arrays深拷贝
 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
  // 是深拷贝 且需有var b = { name : { age : 30 } }; 且b必须是对象自变量(jason) 或者是个数组
  
  //递归
  if ( copyIsArray ) { //数组
  copyIsArray = false;
  clone = src && jQuery.isArray(src) ? src : []; //定义一个空数组

  } else {//jason
  clone = src && jQuery.isPlainObject(src) ? src : {};//看原有的属性有没有且是不是jason定义一个空jason
  }
  // var a = { name : { job : 'it' } }; 看有没有原有的属性 有的话在原有的上边添加
  // var b = { name : {age : 30} };
  // $.extend( true , a , b );//a继承b
  // console.log( a ); a{ name:{ job : 'it' ,age : 30}} 如果只有一个{} 则只有,age : 30
  // Never move original objects, clone(a) them
  target[ name ] = jQuery.extend( deep, clone, copy ); 
  //调用函数本身进行进一步的递归处理 

 // Don't bring in undefined values浅拷贝
 } else if ( copy !== undefined ) {
  target[ name ] = copy; //直接复制因为里边没有对象
 }
 }
 }
 }

 // Return the modified object
 return target;
};

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
简单几行JS Code实现IE邮件转发新浪微博
Jul 03 Javascript
jquery改变disabled的boolean状态的三种方法
Dec 13 Javascript
基于Javascript实现倒计时功能
Feb 22 Javascript
Vue.js每天必学之组件与组件间的通信
Sep 08 Javascript
jQuery.Validate表单验证插件的使用示例详解
Jan 04 Javascript
JS使用面向对象技术实现的tab选项卡效果示例
Feb 28 Javascript
Vue.js事件处理器与表单控件绑定详解
Mar 20 Javascript
addEventListener()与removeEventListener()解析
Apr 20 Javascript
vue项目中实现的微信分享功能示例
Jan 21 Javascript
一篇文章带你使用Typescript封装一个Vue组件(简单易懂)
Jun 05 Javascript
jQuery实现简单QQ聊天框
Aug 27 jQuery
JS开发前端团队展示控制器来为成员引流
Aug 14 Javascript
jQuery web 组件 后台日历价格、库存设置的代码
Oct 14 #Javascript
第一次接触神奇的Bootstrap
Oct 14 #Javascript
js仿手机页面文件下拉刷新效果
Oct 14 #Javascript
前端js实现文件的断点续传 后端PHP文件接收
Oct 14 #Javascript
js关于getImageData跨域问题的解决方法
Oct 14 #Javascript
AngularJS 与Bootstrap实现表格分页实例代码
Oct 14 #Javascript
深入学习js瀑布流布局
Oct 14 #Javascript
You might like
php的控制语句
2006/10/09 PHP
php设计模式 Builder(建造者模式)
2011/06/26 PHP
php中filter函数验证、过滤用户输入的数据
2014/01/13 PHP
thinkphp5.1框架模板布局与模板继承用法分析
2019/07/19 PHP
TP5(thinkPHP5)框架使用ajax实现与后台数据交互的方法小结
2020/02/10 PHP
jQuery使用手册之二 DOM操作
2007/03/24 Javascript
JavaScript异步调用定时方法并停止该方法实现代码
2012/03/16 Javascript
JavaScript插件化开发教程(六)
2015/02/01 Javascript
一看就懂:jsonp详解
2015/06/01 Javascript
javascript如何操作HTML下拉列表标签
2015/08/20 Javascript
JS工作中的小贴士之”闭包“与事件委托的”阻止冒泡“
2016/06/16 Javascript
AngularJS 使用ng-repeat报错 [ngRepeat:dupes]
2017/01/19 Javascript
JS出现失效的情况总结
2017/01/20 Javascript
js实现产品缩略图效果
2017/03/10 Javascript
使用JS和canvas实现gif动图的停止和播放代码
2017/09/01 Javascript
vue项目前端埋点的实现
2019/03/06 Javascript
JavaScript函数式编程(Functional Programming)高阶函数(Higher order functions)用法分析
2019/05/22 Javascript
vue 父组件通过$refs获取子组件的值和方法详解
2019/11/07 Javascript
Vue v-model组件封装(类似弹窗组件)
2020/01/08 Javascript
JS如何生成动态列表
2020/09/22 Javascript
[42:24]完美世界DOTA2联赛循环赛 LBZS vs DM BO2第一场 11.01
2020/11/02 DOTA
详解Python的迭代器、生成器以及相关的itertools包
2015/04/02 Python
基于进程内通讯的python聊天室实现方法
2015/06/28 Python
python实现class对象转换成json/字典的方法
2016/03/11 Python
Python中的Descriptor描述符学习教程
2016/06/02 Python
Python之列表的插入&amp;替换修改方法
2018/06/28 Python
Flask框架响应、调度方法和蓝图操作实例分析
2018/07/24 Python
Windows上安装tensorflow  详细教程(图文详解)
2020/02/04 Python
Python切片列表字符串如何实现切换
2020/08/06 Python
心得体会怎么写
2013/12/30 职场文书
餐饮业创业计划书范文
2014/01/06 职场文书
2014爱耳日宣传教育活动总结
2014/03/09 职场文书
电焊工岗位工作职责
2014/07/09 职场文书
实验心得体会
2014/09/05 职场文书
升职感谢信
2015/01/22 职场文书
Jupyter notebook 不自动弹出网页的解决方案
2021/05/21 Python