针对本话题,我在2015年5月发布了新的文章:深刻剖析 JavaScript 的深复制前端
要实现深复制有不少办法,好比最简单的办法有:node
var cloneObj = JSON.parse(JSON.stringify(obj));
上面这种方法好处是很是简单易用,可是坏处也显而易见,这会抛弃对象的constructor,也就是深复制以后,不管这个对象本来的构造函数是什么,在深复制以后都会变成Object。另外诸如RegExp
对象是没法经过这种方式深复制的。git
因此这里我将介绍一种,我自认为很优美的深复制方法,固然可能也存在问题。若是你发现了个人实现方法有什么问题,请及时让我知道~github
先决条件:
1. 对于任何对象,它可能的类型有Boolean
, Number
, Date
, String
, RegExp
, Array
以及 Object
(全部自定义的对象全都继承于Object
)
2. 咱们必须保留对象的构造函数信息(从而使新对象可使用定义在prototype
上的函数)segmentfault
最重要的一个函数:函数
Object.prototype.clone = function () { var Constructor = this.constructor; var obj = new Constructor(); for (var attr in this) { if (this.hasOwnProperty(attr)) { if (typeof(this[attr]) !== "function") { if (this[attr] === null) { obj[attr] = null; } else { obj[attr] = this[attr].clone(); } } } } return obj; };
定义在Object.prototype
上的clone()
函数是整个方法的核心,对于任意一个非js预约义的对象,都会调用这个函数。而对于全部js预约义的对象,如Number
,Array
等,咱们就要实现一个辅助clone()
函数来实现完整的克隆过程:this
/* Method of Array*/ Array.prototype.clone = function () { var thisArr = this.valueOf(); var newArr = []; for (var i=0; i<thisArr.length; i++) { newArr.push(thisArr[i].clone()); } return newArr; }; /* Method of Boolean, Number, String*/ Boolean.prototype.clone = function() { return this.valueOf(); }; Number.prototype.clone = function() { return this.valueOf(); }; String.prototype.clone = function() { return this.valueOf(); }; /* Method of Date*/ Date.prototype.clone = function() { return new Date(this.valueOf()); }; /* Method of RegExp*/ RegExp.prototype.clone = function() { var pattern = this.valueOf(); var flags = ''; flags += pattern.global ? 'g' : ''; flags += pattern.ignoreCase ? 'i' : ''; flags += pattern.multiline ? 'm' : ''; return new RegExp(pattern.source, flags); };
可能直接定义在预约义对象的方法上,让人感受会有些问题。但在我看来这是一种优美的实现方式。prototype
同时我也在开发一个插件,主要的思想也就是扩展预约义对象的方法。
这个插件叫JustJS
(Github项目地址)
有如下一些特性:
1. 同时支持Web
前端和node.js
使用。
2. 直接对预约义对象的方法进行扩展
3. 使用 J(function(){...})
语句块,决不污染全局命名空间。
目前只写了一小部分,同时也写了些简单的文档,有兴趣的同窗能够看一下,也能够加入我,Fork
个人项目,喜欢的同窗还能够给Star
!插件