123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- var clone = (function() {
- 'use strict';
-
- /**
- * 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)
- * @param `depth` - set to a number if the object is only to be cloned to
- * a particular depth. (optional - defaults to Infinity)
- * @param `prototype` - sets the prototype to be used when cloning an object.
- * (optional - defaults to parent prototype).
- */
- function clone(parent, circular, depth, prototype) {
- var filter;
- if (typeof circular === 'object') {
- depth = circular.depth;
- prototype = circular.prototype;
- filter = circular.filter;
- circular = circular.circular
- }
- // maintain two arrays for circular references, where corresponding parents
- // and children have the same index
- var allParents = [];
- var allChildren = [];
-
- var useBuffer = typeof Buffer != 'undefined';
-
- if (typeof circular == 'undefined')
- circular = true;
-
- if (typeof depth == 'undefined')
- depth = Infinity;
-
- // recurse this function so we don't reset allParents and allChildren
- function _clone(parent, depth) {
- // cloning null always returns null
- if (parent === null)
- return null;
-
- if (depth == 0)
- return parent;
-
- var child;
- var proto;
- if (typeof parent != 'object') {
- return parent;
- }
-
- if (clone.__isArray(parent)) {
- child = [];
- } else if (clone.__isRegExp(parent)) {
- child = new RegExp(parent.source, __getRegExpFlags(parent));
- if (parent.lastIndex) child.lastIndex = parent.lastIndex;
- } else if (clone.__isDate(parent)) {
- child = new Date(parent.getTime());
- } else if (useBuffer && Buffer.isBuffer(parent)) {
- if (Buffer.allocUnsafe) {
- // Node.js >= 4.5.0
- child = Buffer.allocUnsafe(parent.length);
- } else {
- // Older Node.js versions
- child = new Buffer(parent.length);
- }
- parent.copy(child);
- return child;
- } else {
- if (typeof prototype == 'undefined') {
- proto = Object.getPrototypeOf(parent);
- child = Object.create(proto);
- }
- else {
- child = Object.create(prototype);
- proto = prototype;
- }
- }
-
- if (circular) {
- var index = allParents.indexOf(parent);
-
- if (index != -1) {
- return allChildren[index];
- }
- allParents.push(parent);
- allChildren.push(child);
- }
-
- for (var i in parent) {
- var attrs;
- if (proto) {
- attrs = Object.getOwnPropertyDescriptor(proto, i);
- }
-
- if (attrs && attrs.set == null) {
- continue;
- }
- child[i] = _clone(parent[i], depth - 1);
- }
-
- return child;
- }
-
- return _clone(parent, depth);
- }
-
- /**
- * Simple flat clone using prototype, accepts only objects, usefull for property
- * override on FLAT configuration object (no nested props).
- *
- * USE WITH CAUTION! This may not behave as you wish if you do not know how this
- * works.
- */
- clone.clonePrototype = function clonePrototype(parent) {
- if (parent === null)
- return null;
-
- var c = function () {};
- c.prototype = parent;
- return new c();
- };
-
- // private utility functions
-
- function __objToStr(o) {
- return Object.prototype.toString.call(o);
- };
- clone.__objToStr = __objToStr;
-
- function __isDate(o) {
- return typeof o === 'object' && __objToStr(o) === '[object Date]';
- };
- clone.__isDate = __isDate;
-
- function __isArray(o) {
- return typeof o === 'object' && __objToStr(o) === '[object Array]';
- };
- clone.__isArray = __isArray;
-
- function __isRegExp(o) {
- return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
- };
- clone.__isRegExp = __isRegExp;
-
- function __getRegExpFlags(re) {
- var flags = '';
- if (re.global) flags += 'g';
- if (re.ignoreCase) flags += 'i';
- if (re.multiline) flags += 'm';
- return flags;
- };
- clone.__getRegExpFlags = __getRegExpFlags;
-
- return clone;
- })();
-
- if (typeof module === 'object' && module.exports) {
- module.exports = clone;
- }
|