1 var Stack = require('./Stack'),
2 arrayEach = require('./arrayEach'),
3 assignValue = require('./assignValue'),
4 baseAssign = require('./baseAssign'),
5 baseForOwn = require('./baseForOwn'),
6 copyArray = require('./copyArray'),
7 copySymbols = require('./copySymbols'),
8 getTag = require('./getTag'),
9 initCloneArray = require('./initCloneArray'),
10 initCloneByTag = require('./initCloneByTag'),
11 initCloneObject = require('./initCloneObject'),
12 isArray = require('../isArray'),
13 isHostObject = require('./isHostObject'),
14 isObject = require('../isObject');
16 /** `Object#toString` result references. */
17 var argsTag = '[object Arguments]',
18 arrayTag = '[object Array]',
19 boolTag = '[object Boolean]',
20 dateTag = '[object Date]',
21 errorTag = '[object Error]',
22 funcTag = '[object Function]',
23 genTag = '[object GeneratorFunction]',
24 mapTag = '[object Map]',
25 numberTag = '[object Number]',
26 objectTag = '[object Object]',
27 regexpTag = '[object RegExp]',
28 setTag = '[object Set]',
29 stringTag = '[object String]',
30 symbolTag = '[object Symbol]',
31 weakMapTag = '[object WeakMap]';
33 var arrayBufferTag = '[object ArrayBuffer]',
34 float32Tag = '[object Float32Array]',
35 float64Tag = '[object Float64Array]',
36 int8Tag = '[object Int8Array]',
37 int16Tag = '[object Int16Array]',
38 int32Tag = '[object Int32Array]',
39 uint8Tag = '[object Uint8Array]',
40 uint8ClampedTag = '[object Uint8ClampedArray]',
41 uint16Tag = '[object Uint16Array]',
42 uint32Tag = '[object Uint32Array]';
44 /** Used to identify `toStringTag` values supported by `_.clone`. */
45 var cloneableTags = {};
46 cloneableTags[argsTag] = cloneableTags[arrayTag] =
47 cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =
48 cloneableTags[dateTag] = cloneableTags[float32Tag] =
49 cloneableTags[float64Tag] = cloneableTags[int8Tag] =
50 cloneableTags[int16Tag] = cloneableTags[int32Tag] =
51 cloneableTags[mapTag] = cloneableTags[numberTag] =
52 cloneableTags[objectTag] = cloneableTags[regexpTag] =
53 cloneableTags[setTag] = cloneableTags[stringTag] =
54 cloneableTags[symbolTag] = cloneableTags[uint8Tag] =
55 cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] =
56 cloneableTags[uint32Tag] = true;
57 cloneableTags[errorTag] = cloneableTags[funcTag] =
58 cloneableTags[weakMapTag] = false;
61 * The base implementation of `_.clone` and `_.cloneDeep` which tracks
65 * @param {*} value The value to clone.
66 * @param {boolean} [isDeep] Specify a deep clone.
67 * @param {Function} [customizer] The function to customize cloning.
68 * @param {string} [key] The key of `value`.
69 * @param {Object} [object] The parent object of `value`.
70 * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
71 * @returns {*} Returns the cloned value.
73 function baseClone(value, isDeep, customizer, key, object, stack) {
76 result = object ? customizer(value, key, object, stack) : customizer(value);
78 if (result !== undefined) {
81 if (!isObject(value)) {
84 var isArr = isArray(value);
86 result = initCloneArray(value);
88 return copyArray(value, result);
91 var tag = getTag(value),
92 isFunc = tag == funcTag || tag == genTag;
94 if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
95 if (isHostObject(value)) {
96 return object ? value : {};
98 result = initCloneObject(isFunc ? {} : value);
100 return copySymbols(value, baseAssign(result, value));
103 return cloneableTags[tag]
104 ? initCloneByTag(value, tag, isDeep)
105 : (object ? value : {});
108 // Check for circular references and return its corresponding clone.
109 stack || (stack = new Stack);
110 var stacked = stack.get(value);
114 stack.set(value, result);
116 // Recursively populate clone (susceptible to call stack limits).
117 (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {
118 assignValue(result, key, baseClone(subValue, isDeep, customizer, key, value, stack));
120 return isArr ? result : copySymbols(value, result);
123 module.exports = baseClone;