1 var arrayCopy = require('./arrayCopy'),
2 arrayEach = require('./arrayEach'),
3 baseAssign = require('./baseAssign'),
4 baseForOwn = require('./baseForOwn'),
5 initCloneArray = require('./initCloneArray'),
6 initCloneByTag = require('./initCloneByTag'),
7 initCloneObject = require('./initCloneObject'),
8 isArray = require('../lang/isArray'),
9 isObject = require('../lang/isObject');
11 /** `Object#toString` result references. */
12 var argsTag = '[object Arguments]',
13 arrayTag = '[object Array]',
14 boolTag = '[object Boolean]',
15 dateTag = '[object Date]',
16 errorTag = '[object Error]',
17 funcTag = '[object Function]',
18 mapTag = '[object Map]',
19 numberTag = '[object Number]',
20 objectTag = '[object Object]',
21 regexpTag = '[object RegExp]',
22 setTag = '[object Set]',
23 stringTag = '[object String]',
24 weakMapTag = '[object WeakMap]';
26 var arrayBufferTag = '[object ArrayBuffer]',
27 float32Tag = '[object Float32Array]',
28 float64Tag = '[object Float64Array]',
29 int8Tag = '[object Int8Array]',
30 int16Tag = '[object Int16Array]',
31 int32Tag = '[object Int32Array]',
32 uint8Tag = '[object Uint8Array]',
33 uint8ClampedTag = '[object Uint8ClampedArray]',
34 uint16Tag = '[object Uint16Array]',
35 uint32Tag = '[object Uint32Array]';
37 /** Used to identify `toStringTag` values supported by `_.clone`. */
38 var cloneableTags = {};
39 cloneableTags[argsTag] = cloneableTags[arrayTag] =
40 cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =
41 cloneableTags[dateTag] = cloneableTags[float32Tag] =
42 cloneableTags[float64Tag] = cloneableTags[int8Tag] =
43 cloneableTags[int16Tag] = cloneableTags[int32Tag] =
44 cloneableTags[numberTag] = cloneableTags[objectTag] =
45 cloneableTags[regexpTag] = cloneableTags[stringTag] =
46 cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
47 cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
48 cloneableTags[errorTag] = cloneableTags[funcTag] =
49 cloneableTags[mapTag] = cloneableTags[setTag] =
50 cloneableTags[weakMapTag] = false;
52 /** Used for native method references. */
53 var objectProto = Object.prototype;
56 * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
59 var objToString = objectProto.toString;
62 * The base implementation of `_.clone` without support for argument juggling
63 * and `this` binding `customizer` functions.
66 * @param {*} value The value to clone.
67 * @param {boolean} [isDeep] Specify a deep clone.
68 * @param {Function} [customizer] The function to customize cloning values.
69 * @param {string} [key] The key of `value`.
70 * @param {Object} [object] The object `value` belongs to.
71 * @param {Array} [stackA=[]] Tracks traversed source objects.
72 * @param {Array} [stackB=[]] Associates clones with source counterparts.
73 * @returns {*} Returns the cloned value.
75 function baseClone(value, isDeep, customizer, key, object, stackA, stackB) {
78 result = object ? customizer(value, key, object) : customizer(value);
80 if (result !== undefined) {
83 if (!isObject(value)) {
86 var isArr = isArray(value);
88 result = initCloneArray(value);
90 return arrayCopy(value, result);
93 var tag = objToString.call(value),
94 isFunc = tag == funcTag;
96 if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
97 result = initCloneObject(isFunc ? {} : value);
99 return baseAssign(result, value);
102 return cloneableTags[tag]
103 ? initCloneByTag(value, tag, isDeep)
104 : (object ? value : {});
107 // Check for circular references and return corresponding clone.
108 stackA || (stackA = []);
109 stackB || (stackB = []);
111 var length = stackA.length;
113 if (stackA[length] == value) {
114 return stackB[length];
117 // Add the source value to the stack of traversed objects and associate it with its clone.
121 // Recursively populate clone (susceptible to call stack limits).
122 (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {
123 result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB);
128 module.exports = baseClone;