mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-12 03:47:50 +00:00
Add support for symbols to _.clone, _.cloneDeep, and _.isEqual.
This commit is contained in:
38
lodash.js
38
lodash.js
@@ -80,6 +80,7 @@
|
|||||||
regexpTag = '[object RegExp]',
|
regexpTag = '[object RegExp]',
|
||||||
setTag = '[object Set]',
|
setTag = '[object Set]',
|
||||||
stringTag = '[object String]',
|
stringTag = '[object String]',
|
||||||
|
symbolTag = '[object Symbol]',
|
||||||
weakMapTag = '[object WeakMap]';
|
weakMapTag = '[object WeakMap]';
|
||||||
|
|
||||||
var arrayBufferTag = '[object ArrayBuffer]',
|
var arrayBufferTag = '[object ArrayBuffer]',
|
||||||
@@ -253,8 +254,9 @@
|
|||||||
cloneableTags[mapTag] = cloneableTags[numberTag] =
|
cloneableTags[mapTag] = cloneableTags[numberTag] =
|
||||||
cloneableTags[objectTag] = cloneableTags[regexpTag] =
|
cloneableTags[objectTag] = cloneableTags[regexpTag] =
|
||||||
cloneableTags[setTag] = cloneableTags[stringTag] =
|
cloneableTags[setTag] = cloneableTags[stringTag] =
|
||||||
cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
|
cloneableTags[symbolTag] = cloneableTags[uint8Tag] =
|
||||||
cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
|
cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] =
|
||||||
|
cloneableTags[uint32Tag] = true;
|
||||||
cloneableTags[errorTag] = cloneableTags[funcTag] =
|
cloneableTags[errorTag] = cloneableTags[funcTag] =
|
||||||
cloneableTags[weakMapTag] = false;
|
cloneableTags[weakMapTag] = false;
|
||||||
|
|
||||||
@@ -1458,6 +1460,9 @@
|
|||||||
var mapCtorString = Map ? fnToString.call(Map) : '',
|
var mapCtorString = Map ? fnToString.call(Map) : '',
|
||||||
setCtorString = Set ? fnToString.call(Set) : '';
|
setCtorString = Set ? fnToString.call(Set) : '';
|
||||||
|
|
||||||
|
/** Used to convert symbols to strings. */
|
||||||
|
var symbolToString = Symbol ? Symbol.prototype.toString : undefined;
|
||||||
|
|
||||||
/** Used to lookup unminified function names. */
|
/** Used to lookup unminified function names. */
|
||||||
var realNames = {};
|
var realNames = {};
|
||||||
|
|
||||||
@@ -2772,7 +2777,10 @@
|
|||||||
if (value === other) {
|
if (value === other) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
|
if (value == null || other == null || (
|
||||||
|
!(typeof value == 'symbol' || isObject(value)) &&
|
||||||
|
!(typeof other == 'symbol' || isObjectLike(other))
|
||||||
|
)) {
|
||||||
return value !== value && other !== other;
|
return value !== value && other !== other;
|
||||||
}
|
}
|
||||||
return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);
|
return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);
|
||||||
@@ -3750,6 +3758,20 @@
|
|||||||
return arrayReduce(setToArray(set), addSetEntry, new Ctor);
|
return arrayReduce(setToArray(set), addSetEntry, new Ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a clone of `symbol`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object} symbol The symbol to clone.
|
||||||
|
* @returns {Object} Returns the cloned symbol.
|
||||||
|
*/
|
||||||
|
function cloneSymbol(symbol) {
|
||||||
|
var Ctor = symbol.constructor,
|
||||||
|
result = Ctor(symbolToString.call(symbol).slice(7, -1));
|
||||||
|
|
||||||
|
return typeof symbol == 'object' ? Object(result) : result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a clone of `typedArray`.
|
* Creates a clone of `typedArray`.
|
||||||
*
|
*
|
||||||
@@ -4519,6 +4541,9 @@
|
|||||||
// Recursively compare objects (susceptible to call stack limits).
|
// Recursively compare objects (susceptible to call stack limits).
|
||||||
return (isPartial || object.size == other.size) &&
|
return (isPartial || object.size == other.size) &&
|
||||||
equalFunc(convert(object), convert(other), customizer, bitmask | UNORDERED_COMPARE_FLAG);
|
equalFunc(convert(object), convert(other), customizer, bitmask | UNORDERED_COMPARE_FLAG);
|
||||||
|
|
||||||
|
case symbolTag:
|
||||||
|
return symbolToString.call(object) == symbolToString.call(other);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -4831,11 +4856,14 @@
|
|||||||
case stringTag:
|
case stringTag:
|
||||||
return new Ctor(object);
|
return new Ctor(object);
|
||||||
|
|
||||||
|
case regexpTag:
|
||||||
|
return cloneRegExp(object);
|
||||||
|
|
||||||
case setTag:
|
case setTag:
|
||||||
return cloneSet(object);
|
return cloneSet(object);
|
||||||
|
|
||||||
case regexpTag:
|
case symbolTag:
|
||||||
return cloneRegExp(object);
|
return cloneSymbol(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
61
test/test.js
61
test/test.js
@@ -2199,6 +2199,9 @@
|
|||||||
set.add(1);
|
set.add(1);
|
||||||
set.add(2);
|
set.add(2);
|
||||||
}
|
}
|
||||||
|
if (Symbol) {
|
||||||
|
var symbol = Symbol('a');
|
||||||
|
}
|
||||||
var objects = {
|
var objects = {
|
||||||
'`arguments` objects': arguments,
|
'`arguments` objects': arguments,
|
||||||
'arrays': ['a', ''],
|
'arrays': ['a', ''],
|
||||||
@@ -2217,6 +2220,7 @@
|
|||||||
'sets': set,
|
'sets': set,
|
||||||
'strings': 'a',
|
'strings': 'a',
|
||||||
'string objects': Object('a'),
|
'string objects': Object('a'),
|
||||||
|
'symbols': symbol,
|
||||||
'undefined values': undefined
|
'undefined values': undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2309,12 +2313,14 @@
|
|||||||
QUnit.test('`_.' + methodName + '` should clone ' + key, function(assert) {
|
QUnit.test('`_.' + methodName + '` should clone ' + key, function(assert) {
|
||||||
assert.expect(2);
|
assert.expect(2);
|
||||||
|
|
||||||
var isEqual = (key == 'maps' || key == 'sets') ? _.isEqual : lodashStable,
|
var useUnstable = /^(?:maps|sets|symbols)$/.test(key),
|
||||||
|
isEqual = useUnstable ? _.isEqual : lodashStable.isEqual,
|
||||||
|
isObject = useUnstable ? _.isObject : lodashStable.isObject,
|
||||||
actual = func(object);
|
actual = func(object);
|
||||||
|
|
||||||
assert.ok(isEqual(actual, object));
|
assert.ok(isEqual(actual, object));
|
||||||
|
|
||||||
if (lodashStable.isObject(object)) {
|
if (isObject(object)) {
|
||||||
assert.notStrictEqual(actual, object);
|
assert.notStrictEqual(actual, object);
|
||||||
} else {
|
} else {
|
||||||
assert.strictEqual(actual, object);
|
assert.strictEqual(actual, object);
|
||||||
@@ -2358,6 +2364,22 @@
|
|||||||
assert.strictEqual(actual.lastIndex, 3);
|
assert.strictEqual(actual.lastIndex, 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QUnit.test('`_.' + methodName + '` should clone symbol objects', function(assert) {
|
||||||
|
assert.expect(3);
|
||||||
|
|
||||||
|
if (Symbol) {
|
||||||
|
var object = Object(symbol),
|
||||||
|
actual = func(object);
|
||||||
|
|
||||||
|
assert.strictEqual(typeof actual, 'object');
|
||||||
|
assert.strictEqual(typeof actual.valueOf(), 'symbol');
|
||||||
|
assert.notStrictEqual(actual, object);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest(assert, 3);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
QUnit.test('`_.' + methodName + '` should not error on DOM elements', function(assert) {
|
QUnit.test('`_.' + methodName + '` should not error on DOM elements', function(assert) {
|
||||||
assert.expect(1);
|
assert.expect(1);
|
||||||
|
|
||||||
@@ -8113,6 +8135,30 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QUnit.test('should compare symbols', function(assert) {
|
||||||
|
assert.expect(4);
|
||||||
|
|
||||||
|
if (Symbol) {
|
||||||
|
var symbol1 = Symbol('a'),
|
||||||
|
symbol2 = Symbol('b');
|
||||||
|
|
||||||
|
assert.strictEqual(_.isEqual(symbol1, symbol2), false);
|
||||||
|
|
||||||
|
symbol2 = Symbol('a');
|
||||||
|
assert.strictEqual(_.isEqual(symbol1, symbol2), true);
|
||||||
|
|
||||||
|
symbol1 = Symbol(undefined);
|
||||||
|
symbol2 = Symbol('');
|
||||||
|
assert.strictEqual(_.isEqual(symbol1, symbol2), true);
|
||||||
|
|
||||||
|
symbol1 = Symbol(null);
|
||||||
|
assert.strictEqual(_.isEqual(symbol1, symbol2), false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skipTest(assert, 4);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
QUnit.test('should compare typed arrays', function(assert) {
|
QUnit.test('should compare typed arrays', function(assert) {
|
||||||
assert.expect(1);
|
assert.expect(1);
|
||||||
|
|
||||||
@@ -9452,7 +9498,7 @@
|
|||||||
var args = arguments;
|
var args = arguments;
|
||||||
|
|
||||||
QUnit.test('should return `true` for objects', function(assert) {
|
QUnit.test('should return `true` for objects', function(assert) {
|
||||||
assert.expect(12);
|
assert.expect(13);
|
||||||
|
|
||||||
assert.strictEqual(_.isObject(args), true);
|
assert.strictEqual(_.isObject(args), true);
|
||||||
assert.strictEqual(_.isObject([1, 2, 3]), true);
|
assert.strictEqual(_.isObject([1, 2, 3]), true);
|
||||||
@@ -9468,7 +9514,14 @@
|
|||||||
|
|
||||||
if (document) {
|
if (document) {
|
||||||
assert.strictEqual(_.isObject(body), true);
|
assert.strictEqual(_.isObject(body), true);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
|
skipTest(assert);
|
||||||
|
}
|
||||||
|
if (Symbol) {
|
||||||
|
assert.strictEqual(_.isObject(Object(Symbol())), true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
skipTest(assert);
|
skipTest(assert);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user