3 function objectToString(o) {
4 return Object.prototype.toString.call(o);
7 // shim for Node's 'util' package
8 // DO NOT REMOVE THIS! It is required for compatibility with EnderJS (http://enderjs.com/).
10 isArray: function (ar) {
11 return Array.isArray(ar) || (typeof ar === 'object' && objectToString(ar) === '[object Array]');
13 isDate: function (d) {
14 return typeof d === 'object' && objectToString(d) === '[object Date]';
16 isRegExp: function (re) {
17 return typeof re === 'object' && objectToString(re) === '[object RegExp]';
19 getRegExpFlags: function (re) {
21 re.global && (flags += 'g');
22 re.ignoreCase && (flags += 'i');
23 re.multiline && (flags += 'm');
29 if (typeof module === 'object')
30 module.exports = clone;
33 * Clones (copies) an Object using deep copying.
35 * This function supports circular references by default, but if you are certain
36 * there are no circular references in your object, you can save some CPU time
37 * by calling clone(obj, false).
39 * Caution: if `circular` is false and `parent` contains circular references,
40 * your program may enter an infinite loop and crash.
42 * @param `parent` - the object to be cloned
43 * @param `circular` - set to true if the object to be cloned may contain
44 * circular references. (optional - true by default)
45 * @param `depth` - set to a number if the object is only to be cloned to
46 * a particular depth. (optional - defaults to Infinity)
47 * @param `prototype` - sets the prototype to be used when cloning an object.
48 * (optional - defaults to parent prototype).
51 function clone(parent, circular, depth, prototype) {
52 // maintain two arrays for circular references, where corresponding parents
53 // and children have the same index
57 var useBuffer = typeof Buffer != 'undefined';
59 if (typeof circular == 'undefined')
62 if (typeof depth == 'undefined')
65 // recurse this function so we don't reset allParents and allChildren
66 function _clone(parent, depth) {
67 // cloning null always returns null
76 if (typeof parent != 'object') {
80 if (util.isArray(parent)) {
82 } else if (util.isRegExp(parent)) {
83 child = new RegExp(parent.source, util.getRegExpFlags(parent));
84 if (parent.lastIndex) child.lastIndex = parent.lastIndex;
85 } else if (util.isDate(parent)) {
86 child = new Date(parent.getTime());
87 } else if (useBuffer && Buffer.isBuffer(parent)) {
88 child = new Buffer(parent.length);
92 if (typeof prototype == 'undefined') {
93 proto = Object.getPrototypeOf(parent);
94 child = Object.create(proto);
97 child = Object.create(prototype);
103 var index = allParents.indexOf(parent);
106 return allChildren[index];
108 allParents.push(parent);
109 allChildren.push(child);
112 for (var i in parent) {
115 attrs = Object.getOwnPropertyDescriptor(proto, i);
118 if (attrs && attrs.set == null) {
121 child[i] = _clone(parent[i], depth - 1);
127 return _clone(parent, depth);
131 * Simple flat clone using prototype, accepts only objects, usefull for property
132 * override on FLAT configuration object (no nested props).
134 * USE WITH CAUTION! This may not behave as you wish if you do not know how this
137 clone.clonePrototype = function(parent) {
141 var c = function () {};
142 c.prototype = parent;