mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-09 18:37:50 +00:00
Optimize object iteration using Object.keys where faster than for-in loops.
Former-commit-id: 8826f75cf6eaf4233758684e3aae2ccdc3c9f262
This commit is contained in:
@@ -23,11 +23,15 @@
|
|||||||
'iteratorBind',
|
'iteratorBind',
|
||||||
'length',
|
'length',
|
||||||
'methodName',
|
'methodName',
|
||||||
|
'nativeKeys',
|
||||||
'noaccum',
|
'noaccum',
|
||||||
'object',
|
'object',
|
||||||
'objectTypes',
|
'objectTypes',
|
||||||
'prop',
|
'prop',
|
||||||
|
'propIndex',
|
||||||
|
'props',
|
||||||
'property',
|
'property',
|
||||||
|
'propertyIsEnumerable',
|
||||||
'result',
|
'result',
|
||||||
'skipProto',
|
'skipProto',
|
||||||
'slice',
|
'slice',
|
||||||
@@ -59,7 +63,8 @@
|
|||||||
'objectBranch',
|
'objectBranch',
|
||||||
'shadowed',
|
'shadowed',
|
||||||
'top',
|
'top',
|
||||||
'useHas'
|
'useHas',
|
||||||
|
'useNativeKeys'
|
||||||
];
|
];
|
||||||
|
|
||||||
/** Used to minify variables and string values to a single character */
|
/** Used to minify variables and string values to a single character */
|
||||||
@@ -74,6 +79,7 @@
|
|||||||
'all',
|
'all',
|
||||||
'amd',
|
'amd',
|
||||||
'any',
|
'any',
|
||||||
|
'attachEvent',
|
||||||
'bind',
|
'bind',
|
||||||
'bindAll',
|
'bindAll',
|
||||||
'chain',
|
'chain',
|
||||||
|
|||||||
48
lodash.js
48
lodash.js
@@ -131,6 +131,9 @@
|
|||||||
/* Detect if `Function#bind` exists and is inferred to be fast (i.e. all but V8) */
|
/* Detect if `Function#bind` exists and is inferred to be fast (i.e. all but V8) */
|
||||||
var useNativeBind = nativeBind && /\n|Opera/.test(nativeBind + toString.call(window.opera));
|
var useNativeBind = nativeBind && /\n|Opera/.test(nativeBind + toString.call(window.opera));
|
||||||
|
|
||||||
|
/* Detect if `Object.keys` exists and is inferred to be fast (i.e. V8, Opera, IE) */
|
||||||
|
var useNativeKeys = nativeKeys && /^.+$|true/.test(nativeKeys + !!window.attachEvent);
|
||||||
|
|
||||||
/** Detect if sourceURL syntax is usable without erroring */
|
/** Detect if sourceURL syntax is usable without erroring */
|
||||||
try {
|
try {
|
||||||
// Adobe's and Narwhal's JS engines will error
|
// Adobe's and Narwhal's JS engines will error
|
||||||
@@ -279,17 +282,34 @@
|
|||||||
// the following branch is for iterating an object's own/inherited properties
|
// the following branch is for iterating an object's own/inherited properties
|
||||||
'if (objectBranch) {' +
|
'if (objectBranch) {' +
|
||||||
' if (arrayBranch) { %>else {\n<% }' +
|
' if (arrayBranch) { %>else {\n<% }' +
|
||||||
' if (!hasDontEnumBug) { %> var skipProto = typeof <%= iteratedObject %> == \'function\';\n<% } %>' +
|
' if (!hasDontEnumBug) { %>' +
|
||||||
' <%= objectBranch.beforeLoop %>;\n' +
|
' var skipProto = typeof <%= iteratedObject %> == \'function\' && \n' +
|
||||||
|
' propertyIsEnumerable.call(<%= iteratedObject %>, \'prototype\');\n<%' +
|
||||||
|
' } %>' +
|
||||||
|
' <%= objectBranch.beforeLoop %>;\n<%' +
|
||||||
|
|
||||||
|
// iterate own properties using `Object.keys` if it's fast
|
||||||
|
' if (useNativeKeys && useHas) { %>' +
|
||||||
|
' var props = nativeKeys(<%= iteratedObject %>),\n' +
|
||||||
|
' propIndex = -1,\n' +
|
||||||
|
' length = props.length;\n' +
|
||||||
|
' while (++propIndex < length) {\n' +
|
||||||
|
' index = props[propIndex];\n' +
|
||||||
|
' if (!(skipProto && index == \'prototype\')) {\n' +
|
||||||
|
' <%= objectBranch.inLoop %>\n' +
|
||||||
|
' }\n' +
|
||||||
|
' }\n' +
|
||||||
|
|
||||||
|
// else using a for-in loop
|
||||||
|
' <% } else { %>' +
|
||||||
' for (<%= objectBranch.loopExp %>) {' +
|
' for (<%= objectBranch.loopExp %>) {' +
|
||||||
' \n<%' +
|
' \n<%' +
|
||||||
' if (hasDontEnumBug) {' +
|
' if (hasDontEnumBug) {' +
|
||||||
' if (useHas) { %> if (<%= hasExp %>) {\n <% } %>' +
|
' if (useHas) { %> if (<%= hasExp %>) {\n <% } %>' +
|
||||||
' <%= objectBranch.inLoop %>;<%' +
|
' <%= objectBranch.inLoop %>;<%' +
|
||||||
' if (useHas) { %>\n }<% }' +
|
' if (useHas) { %>\n }<% }' +
|
||||||
' }' +
|
' }' +
|
||||||
' else {' +
|
' else { %>' +
|
||||||
' %>' +
|
|
||||||
|
|
||||||
// Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
|
// 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)
|
// (if the prototype or a property on the prototype has been set)
|
||||||
@@ -300,8 +320,9 @@
|
|||||||
' if (!(skipProto && index == \'prototype\')<% if (useHas) { %> && <%= hasExp %><% } %>) {\n' +
|
' if (!(skipProto && index == \'prototype\')<% if (useHas) { %> && <%= hasExp %><% } %>) {\n' +
|
||||||
' <%= objectBranch.inLoop %>\n' +
|
' <%= objectBranch.inLoop %>\n' +
|
||||||
' }' +
|
' }' +
|
||||||
' <% } %>\n' +
|
' <% } %>\n' +
|
||||||
' }' +
|
' }' +
|
||||||
|
' <% } %>' +
|
||||||
|
|
||||||
// Because IE < 9 can't set the `[[Enumerable]]` attribute of an
|
// Because IE < 9 can't set the `[[Enumerable]]` attribute of an
|
||||||
// existing property and the `constructor` property of a prototype
|
// existing property and the `constructor` property of a prototype
|
||||||
@@ -309,7 +330,7 @@
|
|||||||
// property when it infers it's iterating over a `prototype` object.
|
// property when it infers it's iterating over a `prototype` object.
|
||||||
' <% if (hasDontEnumBug) { %>\n' +
|
' <% if (hasDontEnumBug) { %>\n' +
|
||||||
' var ctor = <%= iteratedObject %>.constructor;\n' +
|
' var ctor = <%= iteratedObject %>.constructor;\n' +
|
||||||
' <% for (var k = 0; k < 7; k++) { %>\n' +
|
' <% for (var k = 0; k < 7; k++) { %>\n' +
|
||||||
' index = \'<%= shadowed[k] %>\';\n' +
|
' index = \'<%= shadowed[k] %>\';\n' +
|
||||||
' if (<%' +
|
' if (<%' +
|
||||||
' if (shadowed[k] == \'constructor\') {' +
|
' if (shadowed[k] == \'constructor\') {' +
|
||||||
@@ -479,6 +500,7 @@
|
|||||||
|
|
||||||
data.firstArg = firstArg;
|
data.firstArg = firstArg;
|
||||||
data.hasDontEnumBug = hasDontEnumBug;
|
data.hasDontEnumBug = hasDontEnumBug;
|
||||||
|
data.useNativeKeys = useNativeKeys;
|
||||||
data.hasExp = 'hasOwnProperty.call(' + iteratedObject + ', index)';
|
data.hasExp = 'hasOwnProperty.call(' + iteratedObject + ', index)';
|
||||||
data.iteratedObject = iteratedObject;
|
data.iteratedObject = iteratedObject;
|
||||||
data.shadowed = shadowed;
|
data.shadowed = shadowed;
|
||||||
@@ -496,13 +518,15 @@
|
|||||||
// create the function factory
|
// create the function factory
|
||||||
var factory = Function(
|
var factory = Function(
|
||||||
'arrayClass, compareAscending, funcClass, hasOwnProperty, identity, ' +
|
'arrayClass, compareAscending, funcClass, hasOwnProperty, identity, ' +
|
||||||
'iteratorBind, objectTypes, slice, stringClass, toString',
|
'iteratorBind, objectTypes, nativeKeys, propertyIsEnumerable, ' +
|
||||||
|
'slice, stringClass, toString',
|
||||||
'"use strict"; return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
|
'"use strict"; return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
|
||||||
);
|
);
|
||||||
// return the compiled function
|
// return the compiled function
|
||||||
return factory(
|
return factory(
|
||||||
arrayClass, compareAscending, funcClass, hasOwnProperty, identity,
|
arrayClass, compareAscending, funcClass, hasOwnProperty, identity,
|
||||||
iteratorBind, objectTypes, slice, stringClass, toString
|
iteratorBind, objectTypes, nativeKeys, propertyIsEnumerable, slice,
|
||||||
|
stringClass, toString
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user