Add hasThis to avoid repeatedly checking for this.

Former-commit-id: 15ce8566364ddac60ac01f3a36343c33d9739b77
This commit is contained in:
John-David Dalton
2013-07-18 08:58:40 -07:00
parent 15109f801e
commit 49c032315c
2 changed files with 62 additions and 8 deletions

View File

@@ -1360,6 +1360,18 @@
return result ? result[0] : '';
}
/**
* Gets the `hasThis` fork from `source`.
*
* @private
* @param {String} source The source to inspect.
* @returns {String} Returns the `isFunction` fork.
*/
function getHasThisFork(source) {
var result = source.match(/(?:\s*\/\/.*)*\n( *)if *\(!defineProperty\s*\|\|\s*!reThis\)[\s\S]+?\n\1}/);
return result ? result[0] : '';
}
/**
* Gets the Lo-Dash method assignments snippet from `source`.
*
@@ -1784,21 +1796,34 @@
}
/**
* Removes the binding optimization from `source`.
* Removes `hasThis` and its binding optimizations from `source`.
*
* @private
* @param {String} source The source to process.
* @returns {String} Returns the modified source.
*/
function removeBindingOptimization(source) {
// remove `reThis` from `createCallback`
function removeHasThis(source) {
source = removeFunction(source, 'hasThis');
// remove `hasThis` use `_.createCallback`
source = source.replace(matchFunction(source, 'createCallback'), function(match) {
return match.replace(/\s*\|\|\s*\(reThis[\s\S]+?\)\)\)/, '');
return match.replace(/\s*\|\|\s*!hasThis\(.+?\)/, '');
});
return source;
}
/**
* Removes the `hasThis` fork from `source`.
*
* @private
* @param {String} source The source to process.
* @returns {String} Returns the modified source.
*/
function removeHasThisFork(source) {
return source.replace(getHasThisFork(source), '');
}
/**
* Removes the `Object.keys` object iteration optimization from `source`.
*
@@ -2982,8 +3007,9 @@
);
}
if (isModern) {
source = removeSupportSpliceObjects(source);
source = removeIsArgumentsFork(source);
source = removeHasThisFork(source);
source = removeSupportSpliceObjects(source);
if (isMobile) {
source = replaceSupportProp(source, 'enumPrototypes', 'true');
@@ -3001,7 +3027,7 @@
}
}
if ((isLegacy || isMobile || isUnderscore) && !isLodash('createCallback')) {
source = removeBindingOptimization(source);
source = removeHasThis(source);
}
if (isLegacy || isMobile || isUnderscore) {
if (isMobile || (!isLodash('assign') && !isLodash('defaults') && !isLodash('forIn') && !isLodash('forOwn'))) {
@@ -4080,7 +4106,7 @@
});
// remove forks of removed functions
_.each(['createObject', 'defer', 'isArguments', 'isArray', 'isFunction'], function(funcName) {
_.each(['createObject', 'defer', 'hasThis', 'isArguments', 'isArray', 'isFunction'], function(funcName) {
if (isExcluded(funcName)) {
source = eval('remove' + capitalize(funcName) + 'Fork')(source);
}

View File

@@ -1204,6 +1204,34 @@
return result;
}
/**
* Checks if `func` references the `this` keyword.
*
* @private
* @param {Function} func The function to inspect.
* @returns {Boolean} Returns `true` if `this` is referenced, else `false`.
*/
function hasThis(func) {
var result = func.__hasThis__;
if (typeof result == 'boolean') {
return result;
}
result = reThis.test(fnToString.call(func));
defineProperty(func, '__hasThis__', {
'configurable': true,
'enumerable': false,
'writable': true,
'value': result
});
return result;
}
// fallback for older browsers
if (!defineProperty || !reThis) {
hasThis = function() {
return true;
};
}
/**
* A fallback implementation of `isPlainObject` which checks if a given `value`
* is an object created by the `Object` constructor, assuming objects created
@@ -4784,7 +4812,7 @@
return result;
};
}
if (typeof thisArg == 'undefined' || (reThis && !reThis.test(fnToString.call(func)))) {
if (typeof thisArg == 'undefined' || !hasThis(func)) {
return func;
}
if (argCount === 1) {