mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-10 02:47:50 +00:00
Cleanup iterator template, make _.isEqual avoid the JScript [[DontEnum]] bug and add unit tests.
Former-commit-id: 1325f2184a8572ba688bcf697892782b8a0972e7
This commit is contained in:
106
lodash.js
106
lodash.js
@@ -113,26 +113,29 @@
|
||||
|
||||
// the following branch is for iterating arrays and array-like objects
|
||||
'<% if (arrayBranch) { %>' +
|
||||
' var length = <%= firstArg %>.length; index = -1;\n' +
|
||||
' <% if (objectBranch) { %>if (length === +length) {\n<% } %>' +
|
||||
' var length = <%= firstArg %>.length; index = -1;' +
|
||||
' <% if (objectBranch) { %>\n if (length === +length) {\n<% } %>' +
|
||||
' <%= arrayBranch.beforeLoop %>;\n' +
|
||||
' while (<%= arrayBranch.loopExp %>) {\n' +
|
||||
' <%= arrayBranch.inLoop %>;\n' +
|
||||
' }\n' +
|
||||
' <% if (objectBranch) { %>}\n<% } %>' +
|
||||
'<% } %>' +
|
||||
' }' +
|
||||
' <% if (objectBranch) { %>\n }\n<% }' +
|
||||
'}' +
|
||||
|
||||
// the following branch is for iterating an object's own/inherited properties
|
||||
'<% if (objectBranch) { %>' +
|
||||
' <% if (arrayBranch) { %>\nelse {\n<% } %>' +
|
||||
' <% if (!hasDontEnumBug) { %>var skipProto = typeof <%= iteratedObject %> == \'function\';\n<% } %>' +
|
||||
'if (objectBranch) {' +
|
||||
' if (arrayBranch) { %> else {\n<% }' +
|
||||
' if (!hasDontEnumBug) { %> var skipProto = typeof <%= iteratedObject %> == \'function\';\n<% } %>' +
|
||||
' <%= objectBranch.beforeLoop %>;\n' +
|
||||
' for (<%= objectBranch.loopExp %>) {\n' +
|
||||
' <% if (hasDontEnumBug) { %>' +
|
||||
' <% if (useHas) { %>if (<%= hasExp %>) {\n<% } %>' +
|
||||
' <%= objectBranch.inLoop %>;\n' +
|
||||
' <% if (useHas) { %>}\n<% } %>' +
|
||||
' <% } else { %>' +
|
||||
' <%' +
|
||||
' if (hasDontEnumBug) {' +
|
||||
' if (useHas) { %> if (<%= hasExp %>) {\n <% } %>' +
|
||||
' <%= objectBranch.inLoop %>;\n<%' +
|
||||
' if (useHas) { %> }\n<% }' +
|
||||
' }' +
|
||||
' else {' +
|
||||
' %>' +
|
||||
|
||||
// Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
|
||||
// (if the prototype or a property on the prototype has been set)
|
||||
@@ -140,11 +143,11 @@
|
||||
// value to true. Because of this Lo-Dash standardizes on skipping
|
||||
// the the `prototype` property of functions regardless of its
|
||||
// [[Enumerable]] value.
|
||||
' if (!(skipProto && index == "prototype")\n' +
|
||||
' <% if (useHas) { %>&& <%= hasExp %><% } %>) {\n' +
|
||||
' <%= objectBranch.inLoop %>;\n' +
|
||||
' }\n' +
|
||||
' <% } %>' +
|
||||
' if (!(skipProto && index == "prototype")' +
|
||||
' <% if (useHas) { %>\n && <%= hasExp %><% } %>) {\n' +
|
||||
' <%= objectBranch.inLoop %>;\n' +
|
||||
' }' +
|
||||
' <% } %>' +
|
||||
' }\n' +
|
||||
|
||||
// Because IE < 9 can't set the `[[Enumerable]]` attribute of an
|
||||
@@ -152,19 +155,20 @@
|
||||
// defaults to non-enumerable, Lo-Dash skips the `constructor`
|
||||
// property when it infers it's iterating over a `prototype` object.
|
||||
' <% if (hasDontEnumBug) { %>' +
|
||||
' var ctor = <%= iteratedObject %>.constructor,\n' +
|
||||
' skipCtor = ctor && ctor.prototype === <%= iteratedObject %>;\n' +
|
||||
' for (var j = 0; j < 7; j++) {\n' +
|
||||
' index = shadowed[j];\n' +
|
||||
' if (!(skipCtor && index == "constructor")\n' +
|
||||
' <% if (useHas) { %>&& <%= hasExp %><% } %>) {\n' +
|
||||
' <%= objectBranch.inLoop %>;\n' +
|
||||
' }\n' +
|
||||
' var ctor = <%= iteratedObject %>.constructor,\n' +
|
||||
' skipCtor = ctor && ctor.prototype === <%= iteratedObject %>;\n' +
|
||||
' for (var j = 0; j < 7; j++) {\n' +
|
||||
' index = shadowed[j];\n' +
|
||||
' if (!(skipCtor && index == "constructor") &&\n' +
|
||||
' <%= hasExp %>) {\n' +
|
||||
' <%= objectBranch.inLoop %>;\n' +
|
||||
' }\n' +
|
||||
' <% } %>' +
|
||||
' }\n' +
|
||||
'<% }' +
|
||||
|
||||
' if (arrayBranch) { %>\n }\n<% }' +
|
||||
'} %>' +
|
||||
|
||||
' <% if (arrayBranch) { %>}\n<% } %>' +
|
||||
'<% } %>' +
|
||||
// add code to the bottom of the iteration function
|
||||
'<%= bottom %>;\n' +
|
||||
// finally, return the `result`
|
||||
@@ -283,6 +287,20 @@
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Iterates over an `object`, executing the `callback` for each value in the
|
||||
* `collection`. The `callback` is invoked with 3 arguments, (value, key, object),
|
||||
* and may terminate the loop by explicitly returning `false`.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} object The object to iterate over.
|
||||
* @param {Function} callback The function called per iteration.
|
||||
*/
|
||||
var forOwn = createIterator({
|
||||
'args': 'object, callback',
|
||||
'inLoop': 'if (callback(object[index], index, object) === false) break'
|
||||
});
|
||||
|
||||
/**
|
||||
* Checks if a `value` is an array.
|
||||
*
|
||||
@@ -2298,8 +2316,7 @@
|
||||
if (result) {
|
||||
// deep compare the contents, ignoring non-numeric properties
|
||||
while (size--) {
|
||||
// ensure commutative equality for sparse arrays
|
||||
if (!(result = size in a == size in b && isEqual(a[size], b[size], stack))) {
|
||||
if (!(result = isEqual(a[size], b[size], stack))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2310,23 +2327,20 @@
|
||||
return false;
|
||||
}
|
||||
// deep compare objects
|
||||
for (var prop in a) {
|
||||
if (hasOwnProperty.call(a, prop)) {
|
||||
// count the expected number of properties
|
||||
size++;
|
||||
// deep compare each member
|
||||
if (!(result = hasOwnProperty.call(b, prop) && isEqual(a[prop], b[prop], stack))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
forOwn(a, function(value, prop) {
|
||||
// count the expected number of properties
|
||||
size++;
|
||||
// deep compare each member
|
||||
result = hasOwnProperty.call(b, prop) && isEqual(value, b[prop], stack);
|
||||
// exit loop if `result` is `false`
|
||||
return result;
|
||||
});
|
||||
|
||||
// ensure that both objects contain the same number of properties
|
||||
if (result) {
|
||||
for (prop in b) {
|
||||
if (hasOwnProperty.call(b, prop) && !(size--)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
forOwn(b, function() {
|
||||
return !!(size--);
|
||||
});
|
||||
result = !size;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user