JavaScript 深拷贝 & 浅拷贝
来源:互联网 发布:unity3d awake 编辑:程序博客网 时间:2024/06/05 05:51
在看《你不知道的Js(上卷)》的时候,有遇到深浅拷贝的知识,但是书中只是粗略的讲解,于是乎我便度娘各种有关于深浅拷贝实现的文章。
前提:这里仅仅涉及”引用数据类型”的深、浅拷贝~
浅拷贝
定义:一个引用类型变量复制另一个引用类型变量,将所指向的对象引用地址赋值给另一个变量。实现了两者共同指向同一个对象。只要其中一个改变对象的属性,另一个也会受到影响。
第一种实现方法:
var obj1 = { "name" : "suoz", "color" : ["red","blue"]};var obj2 = obj1; //获取obj1对象的引用地址obj1.name = "lisi";alert(obj2.name); //lisiobj1.color.push("green");alert(obj2.color); //red,blue,green
第二种方法:ES6中提出了Object.assign(),使用它可以实现浅拷贝
var obj1 = { "name" : "suoz", "color" : ["red","blue"]};var obj2 = Object.assign({},obj1);console.log(obj2.name); //suozconsole.log(obj2.color); //red,blue
深拷贝
定义:开辟一个新的内存空间,把被复制对象所有可枚举(Enumerable)属性一一复制过来,两个对象对应两个不同的地址。修改一个对象的属性,另一个对象不会受到影响。
第一种方法:
这是以前学习深拷贝的时候所运用的代码,后来发现有个坑,比如只能支持引用类型[object Object]{}和[object Array][],不能支持[object Function]
//深拷贝function deepClone(obj){ var str; var result = obj instanceof Array?[]:{}; if(typeof obj != 'object'){ return ; }else if(window.JSON){ str = JSON.stringify(obj); result = JSON.parse(str); }else{ for(var i in obj){ if(typeof obj[i] == 'object'){ result[i] = deepClone(obj[i]); }else{ result[i] = obj[i]; } } } return result;}
var obj = { "name" : "suoz", "color" : ["red","blue"], "getName" : function(){ alert("function"); }};var clone_obj = deepClone(obj);console.log(clone_obj); //输出:{name: "suoz", color: ["red", "blue"]}
第二种方法:运用JSON对象,
JSON.sringify():将JS对象转化为JSON格式对象。
JSON.parse():解析JSON格式数据并构造一个由字符串描述的JavaScript对象/值。
var obj = { "name" : "suoz", "color" : ["red"],};var a = JSON.stringify(obj);console.log(a); //{"name":"suoz","color":["red"]}console.log(typeof a); //string//解析JSON格式,根据a的值(string类型)描述创建一个新对象bvar b = JSON.parse(a); console.log(b); //{name: "suoz", color: ["red"]}console.log(Object.prototype.toString.call(b)); //[object Object]console.log(a === b); //false
缺陷:
1. 它能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json直接表示的数据结构。
2.原来对象中的属性都没有了。
var obj = { "name" : "suoz", "color" : ["red","blue"], "getName" : function(){ alert("function"); }};var newObj = { "name" : "lisi", "age" : 20};console.log(newObj);//{name: "lisi", age: 20}//实现深拷贝var newObj = JSON.parse(JSON.stringify(obj));console.log(newObj); //{name: "suoz", color: ["red", "blue"]}
第三种方法:运用JQuery.extend()实现深拷贝。
jQuery.extend第一个参数可以是布尔值,用来设置是否深度拷贝的:
jQuery.extend(true, { a : { a : "a" } }, { a : { b : "b" } } );jQuery.extend( { a : { a : "a" } }, { a : { b : "b" } } );
在实现之前先来看下内部代码,才更好的了解…
jQuery.extend = jQuery.fn.extend = function() { var src, copyIsArray, copy, name, options, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; // 判断第一个参数是不是布尔值 if ( typeof target === "boolean" ) { deep = target; // 如果是布尔值,将第二个参数赋值给target target = arguments[ i ] || {}; i++; } // 如果用户输入的目标对象target不是对象 if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // 如果只输入目标对象,则直接返回该目标对象 if ( i === length ) { target = this; i--; } for ( ; i < length; i++ ) { // 如果源对象不为空 if ( (options = arguments[ i ]) != null ) { // 目标对象开始 赋值 源对象属性 for ( name in options ) { src = target[ name ]; copy = options[ name ]; // 属性赋值完毕 continue if ( target === copy ) { continue; } // 深拷贝 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { //如果属性为[object Array]类型 if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray(src) ? src : []; //如果属性为[object Object]类型 } else { clone = src && jQuery.isPlainObject(src) ? src : {}; } // 递归实现属性的所有子属性都赋值 target[ name ] = jQuery.extend( deep, clone, copy ); // 浅拷贝 或 基本数据类型的赋值 } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // 返回目标对象 return target;};
看了以上的JQuery.extend源代码,那就来实现深拷贝吧..
//首先引入jquery文件var obj = { "name" : "suoz", "color" : ["red","blue"], "getName" : function(){ alert("function"); }};var clone_obj = $.extend(true,{},obj);console.log(clone_obj);//输出:{name: "suoz", color: ["red", "blue"], getName: function}
当然这上面三种方法都没有完美的解决”循环引用”问题
//循环引用var obj = { "arr" : {"obj" : obj}};
总的来说,现在没有一个统一的标准解决办法来实现深复制。
总结(以下以引用类型来说)
浅拷贝相当于引用地址的复制,两个变量指针是共享(引用)同一个对象。
obj1 === obj2
深拷贝相当于为另外一个对象开辟内存空间,并进行递归复制内部属性。两个对象的引用地址是不一样的(即不是引用同一个对象)。
obj1 !== obj2
可以通过”赋值操作符”、Object.assign()、数组遍历赋值等实现浅拷贝。
可以通过自定义代码、JSON对象的方法(JSON.parse和JSON.stringify)、JQuery.extend()等实现深拷贝。
目前来说,并没有统一的标准方法来解决”循环引用”,从而实现真正的深拷贝。
- JavaScript 深拷贝 & 浅拷贝
- Javascript浅拷贝与深拷贝实现
- Javascript浅拷贝与深拷贝实现
- javascript中的深拷贝和浅拷贝
- javascript 深拷贝和浅拷贝
- JavaScript的深拷贝与浅拷贝
- JavaScript深拷贝和浅拷贝
- JavaScript深拷贝和浅拷贝
- javascript中的浅拷贝和深拷贝
- JavaScript的深拷贝和浅拷贝
- javascript中的深拷贝和浅拷贝?
- JavaScript 中深拷贝浅拷贝问题
- Javascript中的深拷贝与浅拷贝
- JavaScript 的深拷贝和浅拷贝
- javaScript中的浅拷贝和深拷贝
- javascript浅拷贝与深拷贝
- JavaScript、JQuery深拷贝、浅拷贝
- JavaScript深拷贝和浅拷贝数组
- swift 基础学习回顾(一)
- 【Leetcode】200. Number of Island
- NYOJ 255
- llinux文件编程2
- mt4
- JavaScript 深拷贝 & 浅拷贝
- [读书笔记]python爬虫-scrapy安装过程常见问题及解决方法
- Mac文件系统
- 缓存淘汰算法之LRU
- Unity常用插件之DoTween(一)
- 学习贵在坚持!
- [python]python常用内置函数
- codeforces544C
- Linux 日志定时轮询流程详解