Ensure _.forIn works over objects with longer inheritance chains in IE < 9.

Former-commit-id: 226223454e71dd8cb6c38a543f1accd915eef3cb
This commit is contained in:
John-David Dalton
2013-05-05 23:58:33 -07:00
parent 4cc3fcb6e8
commit 086669fbe0
2 changed files with 43 additions and 9 deletions

View File

@@ -11,6 +11,7 @@
'argsIndex', 'argsIndex',
'argsLength', 'argsLength',
'callback', 'callback',
'className',
'collection', 'collection',
'ctor', 'ctor',
'guard', 'guard',
@@ -18,15 +19,21 @@
'index', 'index',
'isArguments', 'isArguments',
'isArray', 'isArray',
'isProto',
'isString', 'isString',
'iterable', 'iterable',
'iterated',
'length', 'length',
'keys', 'keys',
'lodash', 'lodash',
'nonEnum',
'nonEnumProps',
'object', 'object',
'objectRef',
'objectTypes', 'objectTypes',
'ownIndex', 'ownIndex',
'ownProps', 'ownProps',
'proto',
'result', 'result',
'skipProto', 'skipProto',
'source', 'source',

View File

@@ -217,6 +217,25 @@
ctorByClass[regexpClass] = RegExp; ctorByClass[regexpClass] = RegExp;
ctorByClass[stringClass] = String; ctorByClass[stringClass] = String;
/** Used to avoid iterating non-enumerable properties in IE < 9 */
var nonEnumProps = {};
nonEnumProps[arrayClass] = nonEnumProps[dateClass] = nonEnumProps[numberClass] = { 'constructor': 1, 'toLocaleString': 1, 'toString': 1, 'valueOf': 1 };
nonEnumProps[boolClass] = nonEnumProps[stringClass] = { 'constructor': 1, 'toString': 1, 'valueOf': 1 };
nonEnumProps[funcClass] = nonEnumProps[regexpClass] = { 'constructor': 1, 'toString': 1 };
nonEnumProps[objectClass] = { 'constructor': 1 };
(function() {
var length = shadowedProps.length;
while (length--) {
var prop = shadowedProps[length];
for (var className in nonEnumProps) {
if (hasOwnProperty.call(nonEnumProps, className) && nonEnumProps[className][prop] !== 1) {
nonEnumProps[className][prop] = 0;
}
}
}
}());
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/** /**
@@ -555,13 +574,21 @@
// defaults to non-enumerable, Lo-Dash skips the `constructor` // defaults to non-enumerable, Lo-Dash skips the `constructor`
// property when it infers it's iterating over a `prototype` object. // property when it infers it's iterating over a `prototype` object.
' <% if (support.nonEnumShadows) { %>\n\n' + ' <% if (support.nonEnumShadows) { %>\n\n' +
' var ctor = iterable.constructor;\n' + ' var iterated = {' +
' <% for (var k = 0; k < 7; k++) { %>\n' + ' <% for (var k = 0; k < 7; k++) { %>\n' +
" '<%= shadowedProps[k] %>': 0<%= (k < 6 ? ',' : '') %>" +
' <% } %>\n' +
' };\n\n' +
' var className = toString.call(iterable),\n' +
' ctor = iterable.constructor,\n' +
' proto = ctor && ctor.prototype,\n' +
' isProto = iterable === proto,\n' +
' nonEnum = nonEnumProps[className];\n\n' +
' <% for (k = 0; k < 7; k++) { %>\n' +
" index = '<%= shadowedProps[k] %>';\n" + " index = '<%= shadowedProps[k] %>';\n" +
' if (<%' + ' if (!iterated[index] && (iterated[index] = (!(isProto && nonEnum[index]) && hasOwnProperty.call(iterable, index))<%' +
" if (shadowedProps[k] == 'constructor') {" + ' if (!useHas) { %> || (!nonEnum[index] && iterable[index] !== objectRef[index])<% }' +
' %>!(ctor && ctor.prototype === iterable) && <%' + ' %>)) {\n' +
' } %>hasOwnProperty.call(iterable, index)) {\n' +
' <%= loop %>\n' + ' <%= loop %>\n' +
' }' + ' }' +
' <% } %>' + ' <% } %>' +
@@ -778,14 +805,14 @@
// create the function factory // create the function factory
var factory = Function( var factory = Function(
'hasOwnProperty, isArguments, isArray, isString, keys, ' + 'hasOwnProperty, isArguments, isArray, isString, keys, lodash, ' +
'lodash, objectTypes', 'objectRef, objectTypes, nonEnumProps, toString',
'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}' 'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
); );
// return the compiled function // return the compiled function
return factory( return factory(
hasOwnProperty, isArguments, isArray, isString, keys, hasOwnProperty, isArguments, isArray, isString, keys, lodash,
lodash, objectTypes objectRef, objectTypes, nonEnumProps, toString
); );
} }