You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					167 lines
				
				4.3 KiB
			
		
		
			
		
	
	
					167 lines
				
				4.3 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								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;
							 | 
						||
| 
								 | 
							
								}
							 |