博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js 对象的深克隆
阅读量:5343 次
发布时间:2019-06-15

本文共 2100 字,大约阅读时间需要 7 分钟。

前端笔试或者面试的时候,很喜欢问的一个问题就是对象的深度克隆,或者说是对象的深度复制。其实这个问题说容易很容易,但是要说全面也挺不易。

  要弄明白对象的克隆,首先要明白js中对象的组成。在js中一切实例皆是对象,具体分为。原始类型对象指的是number、string、boolean等,合成类型对象指的是array、object以及function。

  又或许你刚听说“深度克隆"这个词,简单来说,就是说有个变量a,a的值是个对象(包括基本数据类型),现在你要创建一个变量b,使得它拥有跟a一样的方法和属性等等。但是a和b之间不能相互影响,即a的值的改变不影响b值的变化。

  直接赋值可好?

var a = 1;var b = a;a = 10;console.log(b); // 1var a = 'hello';var b = a;a = 'world';console.log(b); // hellovar a = true;var b = a;a = false;console.log(b); // true

  实践证明某些JavaScript的原始数据类型,如果要克隆直接赋值即可。

  关于function的深度复制:查阅了一些资料,function的深度复制似乎和原始数据类型的深度复制一样。

var a = function() {console.log(1);};var b = a;a = function() {console.log(2);};b(); // 1

  本来我也是这么认为的,思考后我觉得function和普通的对象一样,只是我们在平常应用中习惯了整体的重新赋值,导致它在深度复制中的表现和原始类型一致:

var a = function() {console.log(1);};a.tmp = 10;var b = a;a.tmp = 20;console.log(b.tmp); // 20

  于是乎对于function类型的深度克隆,直接赋值似乎并不应该是一种最好的方法(尽管实际应用中足矣)。那么如何克隆?

function cloneFunction(f){  var fStr = f.toString();  var tmpF = undefined;  eval('tmpF = ' + fStr);  // 静态属性  for(var p in f){    if(f.hasOwnProperty(p)){       tmpF[p] = f[p];    }  }  // 原型  tmpF.prototype = f.prototype;     return tmpF;}

其实这里是不太严谨,比如,如果函数下属性p还是对象,这种情况就需要递归copy,这里只是简单阐述情景;类似的还有number、string、boolean通过new出来的对象;也是一样的情景;

  但是合成类型对象array、object呢?

var a = [0, 1, 2, 3];var b = a;a.push(4);console.log(b); // [0, 1, 2, 3, 4]

  显然与预期不符,为什么会这样?因为原始数据类型储存的是对象的实际数据,而对象类型存储的是对象的引用地址。上面的例子呢也就是说a和b对象引用了同一个地址,无论改变a还是改变b,其实根本操作是一样的,都是对那块空间地址中的值的改变。

  于是我们知道了,对于基本的对象来说,不能只能用=赋值,思索后写下如下代码:

function deepClone(obj) {  var o = obj instanceof Array ? [] : {};  for(var k in obj) {        if(obj.hasOwnProperty(key)){            o[k] = typeof obj[k] === Object ? deepClone(obj[k]) : obj[k];        }    }  o .prototype = obj.prototype;  return o;}var a = [[1, 2, 3], [4, 5, 6, 7]];var b = deepClone(a);console.log(b);

另外一种简单实现:

// 深复制let deepClone= (obj) => {  return JSON.parse(JSON.stringify(obj));};

  似乎可以解决一般的对象(包括Array)的深度克隆了,或许这儿会有疑问,new String(..)这类的也是对象啊,可是这样写你克隆不了啊...但是楼主觉得深度克隆的考点不在这里,可能在于:

  1. 原始数据类型的直接赋值
  2. function的exception
  3. 对象的深度克隆中Array类型的判断
  4. 克隆函数的递归调用

转载于:https://www.cnblogs.com/ysk123/p/10008411.html

你可能感兴趣的文章
[HIHO1184]连通性二·边的双连通分量(双连通分量)
查看>>
Codeforces Round #178 (Div. 2) B. Shaass and Bookshelf 【动态规划】0-1背包
查看>>
SparkStreaming 源码分析
查看>>
【算法】—— 随机音乐的播放算法
查看>>
mysql asyn 示例
查看>>
DataGrid 点击 获取 行 ID
查看>>
git 使用
查看>>
边框圆角方法
查看>>
asp.net WebApi自定义权限验证消息返回
查看>>
php中eval函数的危害与正确禁用方法
查看>>
20172315 2017-2018-2 《程序设计与数据结构》第十一周学习总结
查看>>
MySQL添加、修改、撤销用户数据库操作权限的一些记录
查看>>
ViewBag & ViewData
查看>>
关于谷歌浏览器Chrome正在处理请求的问题解决
查看>>
Git核心技术:在Ubuntu下部署Gitolite服务端
查看>>
平面波展开法总结
查看>>
建造者模式
查看>>
ArraySort--冒泡排序、选择排序、插入排序工具类demo
查看>>
composer 安装laravel
查看>>
8-EasyNetQ之Send & Receive
查看>>