Javascript中的一种深复制实现

[source: unknow] 要实现深复制有很多办法,比如最简单的办法有:

var cloneObj = JSON.parse(JSON.stringify(obj));
1

上面这种方法好处是非常简单易用,但是坏处也显而易见,这会抛弃对象的constructor,也就是深复制之后,无论这个对象原本的构造函数是什么,在深复制之后都会变成Object。另外诸如RegExp对象是无法通过这种方式深复制的。

所以这里我将介绍一种,我自认为很优美的深复制方法,当然可能也存在问题。如果你发现了我的实现方法有什么问题,请及时让我知道~ 先决条件

  1. 对于任何对象,它可能的类型有BooleanNumberDateStringRegExpArray 以及 Object(所有自定义的对象全都继承于Object)
  2. 我们必须保留对象的构造函数信息(从而使新对象可以使用定义在prototype上的函数) 最重要的一个函数:
    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;
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
定义在`Object.prototype`上的`clone()`函数是整个方法的核心,对于任意一个非js预定义的对象,都会调用这个函数。而对于所有js预定义的对象,如`Number`, `Array`等,我们就要实现一个辅助`clone()`函数来实现完整的克隆过程:
```js
	/* 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);
	};
	```
可能直接定义在预定义对象的方法上,让人感觉会有些问题。但在我看来这是一种优美的实现方式。
同时我也在开发一个插件,主要的思想也就是扩展预定义对象的方法。这个插件叫`JustJS`(Github项目地址) 有以下一些特性:
	1.	同时支持Web前端和node.js使用。
	2.	直接对预定义对象的方法进行扩展
	3.	使用` J(function(){...}) `语句块,决不污染全局命名空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
最近更新: 12/11/2018, 1:00:33 PM