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写了一个类似php的print_r输出换行功能
Feb 18 Javascript
jQuery .attr()和.removeAttr()方法操作元素属性示例
Jul 16 Javascript
jQuery对Select的操作大集合(收藏)
Dec 28 Javascript
让浏览器DOM元素最后加载的js方法
Jul 29 Javascript
js实现显示当前状态的导航效果代码
Aug 28 Javascript
以jQuery中$.Deferred对象为例讲解promise对象是如何处理异步问题
Nov 13 Javascript
简洁实用的BootStrap jQuery手风琴插件
Aug 31 Javascript
jQuery插件echarts去掉垂直网格线用法示例
Mar 03 Javascript
jQuery动态添加.active 实现导航效果代码思路详解
Aug 29 jQuery
详解利用eventemitter2实现Vue组件通信
Nov 04 Javascript
Vue左滑组件slider使用详解
Aug 21 Javascript
JS sort排序详细使用方法示例解析
Sep 27 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编程之高级技巧——利用Mysql函数
2006/10/09 PHP
PHP实现把MySQL数据库导出为.sql文件实例(仿PHPMyadmin导出功能)
2014/05/10 PHP
ThinkPHP实现事务回滚示例代码
2014/06/23 PHP
Yii实现多按钮保存与提交的方法
2014/12/03 PHP
PHP实现通过CURL上传文件功能示例
2018/05/30 PHP
自适应图片大小的弹出窗口
2006/07/27 Javascript
JS array 数组详解
2009/03/22 Javascript
模仿jQuery each函数的链式调用
2009/07/22 Javascript
JavaScript 异步调用框架 (Part 4 - 链式调用)
2009/08/04 Javascript
js location.replace与location.reload的区别
2010/09/08 Javascript
js中parseFloat(参数1,参数2)定义和用法及注意事项
2013/01/27 Javascript
js格式化金额可选是否带千分位以及保留精度
2014/01/28 Javascript
z-blog SyntaxHighlighter 长代码无法换行解决办法(jquery)
2014/11/16 Javascript
jQuery插件AjaxFileUpload实现ajax文件上传
2016/05/05 Javascript
详解JavaScript对象类型
2016/06/16 Javascript
js将table的每个td的内容自动赋值给其title属性的方法
2016/10/13 Javascript
vue2.0结合Element实现select动态控制input禁用实例
2017/05/12 Javascript
Vue实现路由跳转和嵌套
2017/06/20 Javascript
javascript实现简易数码时钟
2020/03/30 Javascript
[01:27]DOTA2电竞之夜 今夜共饮庆功酒
2014/08/02 DOTA
Python的subprocess模块总结
2014/11/07 Python
asyncio 的 coroutine对象 与 Future对象使用指南
2016/09/11 Python
利用OpenCV中对图像数据进行64F和8U转换的方式
2020/06/03 Python
如何用用Python将地址标记在地图上
2021/02/07 Python
uniapp+Html5端实现PC端适配
2020/07/15 HTML / CSS
Whistles官网:英国女装品牌
2020/08/14 全球购物
3个CCIE对一个工程师的面试题
2012/05/06 面试题
理工大学毕业生自荐信范文
2014/02/22 职场文书
爱心捐款倡议书范文
2014/05/12 职场文书
幼儿园课题方案
2014/06/09 职场文书
工地宣传标语
2014/06/18 职场文书
2014年财务科工作总结
2014/11/11 职场文书
2014年数学教研组工作总结
2014/12/06 职场文书
Python基础 括号()[]{}的详解
2021/11/07 Python
类和原型的设计模式之复制与委托差异
2022/07/07 Javascript
Python使用plt.boxplot()函数绘制箱图、常用方法以及含义详解
2022/08/14 Python