Optimize this binding in iterator methods and remove _.bind as a dependency for several methods.

Former-commit-id: 60af002cd80758fea81fbff9c2b20b1ccf3ccffd
This commit is contained in:
John-David Dalton
2012-05-31 10:14:01 -05:00
parent f13a0cc7e0
commit b432721fe5
3 changed files with 41 additions and 26 deletions

View File

@@ -72,15 +72,15 @@
'delay': [], 'delay': [],
'difference': ['indexOf'], 'difference': ['indexOf'],
'escape': [], 'escape': [],
'every': ['bind', 'createIterator', 'identity'], 'every': ['createIterator', 'identity'],
'extend': ['createIterator'], 'extend': ['createIterator'],
'filter': ['bind', 'createIterator', 'identity'], 'filter': ['createIterator', 'identity'],
'find': ['bind', 'createIterator'], 'find': ['createIterator'],
'first': [], 'first': [],
'flatten': ['isArray'], 'flatten': ['isArray'],
'forEach': ['bind', 'createIterator'], 'forEach': ['createIterator'],
'functions': ['createIterator'], 'functions': ['createIterator'],
'groupBy': ['bind', 'createIterator'], 'groupBy': ['createIterator'],
'has': [], 'has': [],
'identity': [], 'identity': [],
'indexOf': ['sortedIndex'], 'indexOf': ['sortedIndex'],
@@ -106,10 +106,10 @@
'keys': ['createIterator'], 'keys': ['createIterator'],
'last': [], 'last': [],
'lastIndexOf': [], 'lastIndexOf': [],
'map': ['bind', 'createIterator', 'identity'], 'map': ['createIterator', 'identity'],
'max': ['bind'], 'max': [],
'memoize': [], 'memoize': [],
'min': ['bind'], 'min': [],
'mixin': ['forEach'], 'mixin': ['forEach'],
'noConflict': [], 'noConflict': [],
'once': [], 'once': [],
@@ -117,20 +117,20 @@
'pick': [], 'pick': [],
'pluck': ['createIterator'], 'pluck': ['createIterator'],
'range': [], 'range': [],
'reduce': ['bind', 'createIterator'], 'reduce': ['createIterator'],
'reduceRight': ['bind', 'keys'], 'reduceRight': ['keys'],
'reject': ['bind', 'createIterator', 'identity'], 'reject': ['createIterator', 'identity'],
'rest': [], 'rest': [],
'result': [], 'result': [],
'shuffle': [], 'shuffle': [],
'size': ['keys'], 'size': ['keys'],
'some': ['bind', 'createIterator', 'identity'], 'some': ['createIterator', 'identity'],
'sortBy': ['bind', 'map', 'pluck'], 'sortBy': ['map', 'pluck'],
'sortedIndex': [], 'sortedIndex': [],
'tap': [], 'tap': [],
'template': ['escape'], 'template': ['escape'],
'throttle': [], 'throttle': [],
'times': ['bind'], 'times': [],
'toArray': ['values'], 'toArray': ['values'],
'union': ['indexOf'], 'union': ['indexOf'],
'uniq': ['indexOf'], 'uniq': ['indexOf'],

View File

@@ -9,7 +9,6 @@
var compiledVars = [ var compiledVars = [
'accumulator', 'accumulator',
'arrayClass', 'arrayClass',
'bind',
'callback', 'callback',
'className', 'className',
'collection', 'collection',
@@ -19,6 +18,7 @@
'hasOwnProperty', 'hasOwnProperty',
'identity', 'identity',
'index', 'index',
'iteratorBind',
'length', 'length',
'object', 'object',
'objectTypes', 'objectTypes',

View File

@@ -271,7 +271,7 @@
' callback = identity\n' + ' callback = identity\n' +
'}\n' + '}\n' +
'else if (thisArg) {\n' + 'else if (thisArg) {\n' +
' callback = bind(callback, thisArg)\n' + ' callback = iteratorBind(callback, thisArg)\n' +
'}', '}',
'inLoop': 'callback(collection[index], index, collection)' 'inLoop': 'callback(collection[index], index, collection)'
}; };
@@ -304,7 +304,7 @@
/** Reusable iterator options for `find` and `forEach` */ /** Reusable iterator options for `find` and `forEach` */
var forEachIteratorOptions = { var forEachIteratorOptions = {
'top': 'if (thisArg) callback = bind(callback, thisArg)' 'top': 'if (thisArg) callback = iteratorBind(callback, thisArg)'
}; };
/** Reusable iterator options for `map`, `pluck`, and `values` */ /** Reusable iterator options for `map`, `pluck`, and `values` */
@@ -418,13 +418,13 @@
} }
// create the function factory // create the function factory
var factory = Function( var factory = Function(
'arrayClass, bind, funcClass, hasOwnProperty, identity, objectTypes, ' + 'arrayClass, funcClass, hasOwnProperty, identity, iteratorBind, objectTypes, ' +
'stringClass, toString, undefined', 'stringClass, toString, undefined',
'"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, bind, funcClass, hasOwnProperty, identity, objectTypes, arrayClass, funcClass, hasOwnProperty, identity, iteratorBind, objectTypes,
stringClass, toString stringClass, toString
); );
} }
@@ -453,6 +453,21 @@
return '\\' + escapes[match]; return '\\' + escapes[match];
} }
/**
* Creates a new function that, when called, invokes `func` with the `this`
* binding of `thisArg` and the arguments (value, index, object).
*
* @private
* @param {Function} func The function to bind.
* @param {Mixed} [thisArg] The `this` binding of `func`.
* @returns {Function} Returns the new bound function.
*/
function iteratorBind(func, thisArg) {
return function(value, index, object) {
return func.call(thisArg, value, index, object);
};
}
/** /**
* A no-operation function. * A no-operation function.
* *
@@ -697,7 +712,7 @@
'init': 'accumulator', 'init': 'accumulator',
'top': 'top':
'var noaccum = arguments.length < 3;\n' + 'var noaccum = arguments.length < 3;\n' +
'if (thisArg) callback = bind(callback, thisArg)', 'if (thisArg) callback = iteratorBind(callback, thisArg)',
'beforeLoop': { 'beforeLoop': {
'array': 'if (noaccum) result = collection[++index]' 'array': 'if (noaccum) result = collection[++index]'
}, },
@@ -741,7 +756,7 @@
noaccum = arguments.length < 3; noaccum = arguments.length < 3;
if(thisArg) { if(thisArg) {
callback = bind(callback, thisArg); callback = iteratorBind(callback, thisArg);
} }
if (length === +length) { if (length === +length) {
if (length && noaccum) { if (length && noaccum) {
@@ -1015,7 +1030,7 @@
result = {}; result = {};
if (isFunc && thisArg) { if (isFunc && thisArg) {
callback = bind(callback, thisArg); callback = iteratorBind(callback, thisArg);
} }
while (++index < length) { while (++index < length) {
value = array[index]; value = array[index];
@@ -1053,7 +1068,7 @@
var prop = callback; var prop = callback;
callback = function(array) { return array[prop]; }; callback = function(array) { return array[prop]; };
} else if (thisArg) { } else if (thisArg) {
callback = bind(callback, thisArg); callback = iteratorBind(callback, thisArg);
} }
return pluck(map(array, function(value, index) { return pluck(map(array, function(value, index) {
return { return {
@@ -1279,7 +1294,7 @@
return result; return result;
} }
if (thisArg) { if (thisArg) {
callback = bind(callback, thisArg); callback = iteratorBind(callback, thisArg);
} }
while (++index < length) { while (++index < length) {
current = callback(array[index], index, array); current = callback(array[index], index, array);
@@ -1325,7 +1340,7 @@
return result; return result;
} }
if (thisArg) { if (thisArg) {
callback = bind(callback, thisArg); callback = iteratorBind(callback, thisArg);
} }
while (++index < length) { while (++index < length) {
current = callback(array[index], index, array); current = callback(array[index], index, array);
@@ -1640,7 +1655,7 @@
* @memberOf _ * @memberOf _
* @category Functions * @category Functions
* @param {Function|Object} func The function to bind or the object the method belongs to. * @param {Function|Object} func The function to bind or the object the method belongs to.
* @param @param {Mixed} [thisArg] The `this` binding of `func` or the method name. * @param {Mixed} [thisArg] The `this` binding of `func` or the method name.
* @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
* @returns {Function} Returns the new bound function. * @returns {Function} Returns the new bound function.
* @example * @example