From 14c8863657070a24256456afcc7460051bfdc165 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 6 May 2012 17:55:23 -0400 Subject: [PATCH] lodash: Add native method overwrite detection and optimize `bind` for native `bind`. [jddalton] Former-commit-id: d968957e494fb828df155d2f9b0d3faf24e38b5e --- lodash.js | 45 +++++++++++++++++++++++++++++++++++++-------- test/index.html | 15 ++++++++++++++- test/test.js | 8 ++++++++ 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/lodash.js b/lodash.js index f2af6917a..e97ac0760 100644 --- a/lodash.js +++ b/lodash.js @@ -29,6 +29,9 @@ /** Used to restore the original `_` reference in `noConflict` */ var oldDash = window._; + /** Used to detect if a method is native */ + var reNative = /\{\s*\[native code\]\s*\}/; + /** Used to match tokens in template text */ var reToken = /__token__(\d+)/g; @@ -65,10 +68,14 @@ slice = ArrayProto.slice, toString = ObjectProto.toString; + /* Used if `Function#bind` exists and is inferred to be fast (i.e. all but V8) */ + var nativeBind = reNative.test(nativeBind = slice.bind) && + (/\n/.test(nativeBind) || toString.call(window.opera) == '[object Opera]') && nativeBind; + /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeIsArray = Array.isArray, + var nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray, nativeIsFinite = window.isFinite, - nativeKeys = Object.keys; + nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys; /** Timer shortcuts */ var clearTimeout = window.clearTimeout, @@ -1548,19 +1555,41 @@ * // => 'hi moe!' */ function bind(func, thisArg) { - var args = slice.call(arguments, 2), - argsLength = args.length, + var methodName, isFunc = toString.call(func) == funcClass; // juggle arguments if (!isFunc) { - var methodName = thisArg; + methodName = thisArg; thisArg = func; } + // use native `Function#bind` if faster + else if (nativeBind) { + func = nativeBind.call.apply(nativeBind, arguments); + return function() { + return func.apply(undefined, arguments); + }; + } + + var partialArgs = slice.call(arguments, 2), + partialArgsLength = partialArgs.length; + return function() { - push.apply(args, arguments); - var result = (isFunc ? func : thisArg[methodName]).apply(thisArg, args); - args.length = argsLength; + var result, + args = arguments; + + if (!isFunc) { + func = thisArg[methodName]; + } + if (partialArgsLength) { + if (args.length) { + partialArgs.length = partialArgsLength; + push.apply(partialArgs, args); + } + args = partialArgs; + } + result = args.length ? func.apply(thisArg, args) : func.call(thisArg); + partialArgs.length = partialArgsLength; return result; }; } diff --git a/test/index.html b/test/index.html index 182ad8910..3d9f0735c 100644 --- a/test/index.html +++ b/test/index.html @@ -12,7 +12,20 @@

    - + + +