mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-14 12:47:49 +00:00
lodash: Add native method overwrite detection and optimize bind for native bind. [jddalton]
Former-commit-id: d968957e494fb828df155d2f9b0d3faf24e38b5e
This commit is contained in:
45
lodash.js
45
lodash.js
@@ -29,6 +29,9 @@
|
|||||||
/** Used to restore the original `_` reference in `noConflict` */
|
/** Used to restore the original `_` reference in `noConflict` */
|
||||||
var oldDash = window._;
|
var oldDash = window._;
|
||||||
|
|
||||||
|
/** Used to detect if a method is native */
|
||||||
|
var reNative = /\{\s*\[native code\]\s*\}/;
|
||||||
|
|
||||||
/** Used to match tokens in template text */
|
/** Used to match tokens in template text */
|
||||||
var reToken = /__token__(\d+)/g;
|
var reToken = /__token__(\d+)/g;
|
||||||
|
|
||||||
@@ -65,10 +68,14 @@
|
|||||||
slice = ArrayProto.slice,
|
slice = ArrayProto.slice,
|
||||||
toString = ObjectProto.toString;
|
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 */
|
/* 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,
|
nativeIsFinite = window.isFinite,
|
||||||
nativeKeys = Object.keys;
|
nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys;
|
||||||
|
|
||||||
/** Timer shortcuts */
|
/** Timer shortcuts */
|
||||||
var clearTimeout = window.clearTimeout,
|
var clearTimeout = window.clearTimeout,
|
||||||
@@ -1548,19 +1555,41 @@
|
|||||||
* // => 'hi moe!'
|
* // => 'hi moe!'
|
||||||
*/
|
*/
|
||||||
function bind(func, thisArg) {
|
function bind(func, thisArg) {
|
||||||
var args = slice.call(arguments, 2),
|
var methodName,
|
||||||
argsLength = args.length,
|
|
||||||
isFunc = toString.call(func) == funcClass;
|
isFunc = toString.call(func) == funcClass;
|
||||||
|
|
||||||
// juggle arguments
|
// juggle arguments
|
||||||
if (!isFunc) {
|
if (!isFunc) {
|
||||||
var methodName = thisArg;
|
methodName = thisArg;
|
||||||
thisArg = func;
|
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() {
|
return function() {
|
||||||
push.apply(args, arguments);
|
var result,
|
||||||
var result = (isFunc ? func : thisArg[methodName]).apply(thisArg, args);
|
args = arguments;
|
||||||
args.length = argsLength;
|
|
||||||
|
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;
|
return result;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,20 @@
|
|||||||
<h2 id="qunit-userAgent"></h2>
|
<h2 id="qunit-userAgent"></h2>
|
||||||
<ol id="qunit-tests"></ol>
|
<ol id="qunit-tests"></ol>
|
||||||
<script src="../vendor/qunit/qunit/qunit.js"></script>
|
<script src="../vendor/qunit/qunit/qunit.js"></script>
|
||||||
<script>var _2, _3, _ = 1;</script>
|
<script>
|
||||||
|
var _2,
|
||||||
|
_3 = Object.keys;
|
||||||
|
|
||||||
|
Object.keys = function() { return []; };
|
||||||
|
</script>
|
||||||
|
<script src="../lodash.js"></script>
|
||||||
|
<script>
|
||||||
|
var lodashBadKeys = _,
|
||||||
|
_ = 1;
|
||||||
|
|
||||||
|
Object.keys = _3;
|
||||||
|
_3 = void 0;
|
||||||
|
</script>
|
||||||
<script src="../lodash.js"></script>
|
<script src="../lodash.js"></script>
|
||||||
<script src="../vendor/requirejs/require.js"></script>
|
<script src="../vendor/requirejs/require.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -62,6 +62,14 @@
|
|||||||
skipTest(1)
|
skipTest(1)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('avoids overwritten native methods', function() {
|
||||||
|
if (window.lodashBadKeys) {
|
||||||
|
notDeepEqual(lodashBadKeys.keys({ 'a': 1 }), []);
|
||||||
|
} else {
|
||||||
|
skipTest(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
}());
|
}());
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|||||||
Reference in New Issue
Block a user