forked from pvorb/clone
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathclone.js
110 lines (103 loc) · 3.5 KB
/
clone.js
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
module.exports = clone;
/**
* Clones (copies) an Object using deep copying.
*
* This function supports circular references by default, but if you are certain
* there are no circular references in your object, you can save some CPU time
* by calling clone(obj, false).
*
* Caution: if `circular` is false and `parent` contains circular references,
* your program may enter an infinite loop and crash.
*
* @param `parent` - the object to be cloned
* @param `circular` - set to true if the object to be cloned may contain
* circular references. (optional - true by default)
*/
function clone(parent, circular) {
if (typeof circular == 'undefined')
circular = true;
var i;
if (circular) {
var circularParent = {};
var circularResolved = {};
var circularReplace = [];
function _clone(parent, context, child, cIndex) {
var i; // Use local context within this function
// Deep clone all properties of parent into child
if (typeof parent == 'object') {
if (parent == null)
return parent;
// Check for circular references
for(i in circularParent)
if (circularParent[i] === parent) {
// We found a circular reference
circularReplace.push({'resolveTo': i, 'child': child, 'i': cIndex});
return null; //Just return null for now...
// we will resolve circular references later
}
// Add to list of all parent objects
circularParent[context] = parent;
// Now continue cloning...
if (parent.constructor.name === 'Array') {
child = [];
for(i in parent)
child[i] = _clone(parent[i], context + '[' + i + ']', child, i);
}
else if (parent.constructor.name === 'Date')
child = new Date(parent.getTime());
else if (parent.constructor.name === 'RegExp')
child = new RegExp(parent.source);
else {
child = {};
// Also copy prototype over to new cloned object
child.__proto__ = parent.__proto__;
for(i in parent)
child[i] = _clone(parent[i], context + '[' + i + ']', child, i);
}
// Add to list of all cloned objects
circularResolved[context] = child;
}
else
child = parent; //Just a simple shallow copy will do
return child;
}
var cloned = _clone(parent, '*');
// Now this object has been cloned. Let's check to see if there are any
// circular references for it
for(i in circularReplace) {
var c = circularReplace[i];
if (c && c.child && c.i in c.child) {
c.child[c.i] = circularResolved[c.resolveTo];
}
}
return cloned;
}
else {
// Deep clone all properties of parent into child
var child;
if (typeof parent == 'object') {
if (parent == null)
return parent;
if (parent.constructor.name === 'Array') {
child = [];
for(i in parent)
child[i] = clone(parent[i], circular);
}
else if (parent.constructor.name === 'Date')
child = new Date(parent.getTime() );
else if (parent.constructor.name === 'RegExp')
child = new RegExp(parent.source);
else {
child = {};
child.__proto__ = parent.__proto__;
for(i in parent)
child[i] = clone(parent[i], circular);
}
}
else
child = parent; // Just a simple shallow clone will do
return child;
}
}
// see: clonePrototype.js
clone.clonePrototype = require('./clonePrototype.js');