|
131 | 131 | /* Detect if `Function#bind` exists and is inferred to be fast (i.e. all but V8) */
|
132 | 132 | var useNativeBind = nativeBind && /\n|Opera/.test(nativeBind + toString.call(window.opera));
8000
div>
|
133 | 133 |
|
| 134 | + /* Detect if `Object.keys` exists and is inferred to be fast (i.e. V8, Opera, IE) */ |
| 135 | + var useNativeKeys = nativeKeys && /^.+$|true/.test(nativeKeys + !!window.attachEvent); |
| 136 | + |
134 | 137 | /** Detect if sourceURL syntax is usable without erroring */
|
135 | 138 | try {
|
136 | 139 | // Adobe's and Narwhal's JS engines will error
|
|
279 | 282 | // the following branch is for iterating an object's own/inherited properties
|
280 | 283 | 'if (objectBranch) {' +
|
281 | 284 | ' if (arrayBranch) { %>else {\n<% }' +
|
282 |
| - ' if (!hasDontEnumBug) { %> var skipProto = typeof <%= iteratedObject %> == \'function\';\n<% } %>' + |
283 |
| - ' <%= objectBranch.beforeLoop %>;\n' + |
| 285 | + ' if (!hasDontEnumBug) { %>' + |
| 286 | + ' var skipProto = typeof <%= iteratedObject %> == \'function\' && \n' + |
| 287 | + ' propertyIsEnumerable.call(<%= iteratedObject %>, \'prototype\');\n<%' + |
| 288 | + ' } %>' + |
| 289 | + ' <%= objectBranch.beforeLoop %>;\n<%' + |
| 290 | + |
| 291 | + // iterate own properties using `Object.keys` if it's fast |
| 292 | + ' if (useNativeKeys && useHas) { %>' + |
| 293 | + ' var props = nativeKeys(<%= iteratedObject %>),\n' + |
| 294 | + ' propIndex = -1,\n' + |
| 295 | + ' length = props.length;\n' + |
| 296 | + ' while (++propIndex < length) {\n' + |
| 297 | + ' index = props[propIndex];\n' + |
| 298 | + ' if (!(skipProto && index == \'prototype\')) {\n' + |
| 299 | + ' <%= objectBranch.inLoop %>\n' + |
| 300 | + ' }\n' + |
| 301 | + ' }\n' + |
| 302 | + |
| 303 | + // else using a for-in loop |
| 304 | + ' <% } else { %>' + |
284 | 305 | ' for (<%= objectBranch.loopExp %>) {' +
|
285 | 306 | ' \n<%' +
|
286 |
| - ' if (hasDontEnumBug) {' + |
287 |
| - ' if (useHas) { %> if (<%= hasExp %>) {\n <% } %>' + |
| 307 | + ' if (hasDontEnumBug) {' + |
| 308 | + ' if (useHas) { %> if (<%= hasExp %>) {\n <% } %>' + |
288 | 309 | ' <%= objectBranch.inLoop %>;<%' +
|
289 |
| - ' if (useHas) { %>\n }<% }' + |
290 |
| - ' }' + |
291 |
| - ' else {' + |
292 |
| - ' %>' + |
| 310 | + ' if (useHas) { %>\n }<% }' + |
| 311 | + ' }' + |
| 312 | + ' else { %>' + |
293 | 313 |
|
294 | 314 | // Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
|
295 | 315 | // (if the prototype or a property on the prototype has been set)
|
|
300 | 320 | ' if (!(skipProto && index == \'prototype\')<% if (useHas) { %> && <%= hasExp %><% } %>) {\n' +
|
301 | 321 | ' <%= objectBranch.inLoop %>\n' +
|
302 | 322 | ' }' +
|
303 |
| - ' <% } %>\n' + |
| 323 | + ' <% } %>\n' + |
304 | 324 | ' }' +
|
| 325 | + ' <% } %>' + |
305 | 326 |
|
306 | 327 | // Because IE < 9 can't set the `[[Enumerable]]` attribute of an
|
307 | 328 | // existing property and the `constructor` property of a prototype
|
308 | 329 | // defaults to non-enumerable, Lo-Dash skips the `constructor`
|
309 | 330 | // property when it infers it's iterating over a `prototype` object.
|
310 | 331 | ' <% if (hasDontEnumBug) { %>\n' +
|
311 | 332 | ' var ctor = <%= iteratedObject %>.constructor;\n' +
|
312 |
| - ' <% for (var k = 0; k < 7; k++) { %>\n' + |
| 333 | + ' <% for (var k = 0; k < 7; k++) { %>\n' + |
313 | 334 | ' index = \'<%= shadowed[k] %>\';\n' +
|
314 | 335 | ' if (<%' +
|
315 | 336 | ' if (shadowed[k] == \'constructor\') {' +
|
|
479 | 500 |
|
480 | 501 | data.firstArg = firstArg;
|
481 | 502 | data.hasDontEnumBug = hasDontEnumBug;
|
| 503 | + data.useNativeKeys = useNativeKeys; |
482 | 504 | data.hasExp = 'hasOwnProperty.call(' + iteratedObject + ', index)';
|
483 | 505 | data.iteratedObject = iteratedObject;
|
484 | 506 | data.shadowed = shadowed;
|
|
496 | 518 | // create the function factory
|
497 | 519 | var factory = Function(
|
498 | 520 | 'arrayClass, compareAscending, funcClass, hasOwnProperty, identity, ' +
|
499 |
| - 'iteratorBind, objectTypes, slice, stringClass, toString', |
| 521 | + 'iteratorBind, objectTypes, nativeKeys, propertyIsEnumerable, ' + |
| 522 | + 'slice, stringClass, toString', |
500 | 523 | '"use strict"; return function(' + args + ') {\n' + iteratorTemplate(data)
7068
+ '\n}'
|
501 | 524 | );
|
502 | 525 | // return the compiled function
|
503 | 526 | return factory(
|
504 | 527 | arrayClass, compareAscending, funcClass, hasOwnProperty, identity,
|
505 |
| - iteratorBind, objectTypes, slice, stringClass, toString |
| 528 | + iteratorBind, objectTypes, nativeKeys, propertyIsEnumerable, slice, |
| 529 | + stringClass, toString |
506 | 530 | );
|
507 | 531 | }
|
508 | 532 |
|
|
0 commit comments