Ensure _.keys use in createIterator is consistent per build.

Former-commit-id: a4e0aef177d4d1c26ed5ce088574b591a6666d0d
This commit is contained in:
John-David Dalton
2013-03-19 23:50:56 -07:00
parent ba85d5d351
commit 743aa472f0
10 changed files with 836 additions and 846 deletions

294
dist/lodash.js vendored
View File

@@ -180,7 +180,6 @@
/** Detect various environments */
var isIeOpera = reNative.test(context.attachEvent),
isJSC = !/\n{2,}/.test(Function()),
isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera);
/** Used to lookup a built-in constructor by [[Class]] */
@@ -259,14 +258,6 @@
*/
support.fastBind = nativeBind && !isV8;
/**
* Detect if `Object.keys` exists and is inferred to be fast (Firefox, IE, Opera, V8).
*
* @memberOf _.support
* @type Boolean
*/
support.fastKeys = nativeKeys && (isIeOpera || isV8 || !isJSC);
/**
* By default, the template delimiters used by Lo-Dash are similar to those in
* embedded Ruby (ERB). Change the following template settings to use alternative
@@ -341,7 +332,9 @@
var __p = 'var index, iterable = ' +
(obj.firstArg) +
', result = iterable;\nif (!iterable) return result;\n' +
', result = ' +
(obj.init) +
';\nif (!iterable) return result;\n' +
(obj.top) +
';\n';
if (obj.arrays) {
@@ -352,8 +345,8 @@
'\n }\n}\nelse { ';
}
if (support.fastKeys && obj.useHas) {
__p += '\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] ? nativeKeys(iterable) : [],\n length = ownProps.length;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n ' +
if (obj.useHas && obj.useKeys) {
__p += '\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] ? keys(iterable) : [],\n length = ownProps.length;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n ' +
(obj.loop) +
'\n } ';
} else {
@@ -563,9 +556,11 @@
// iterator options
'arrays': 'isArray(iterable)',
'bottom': '',
'init': 'iterable',
'loop': '',
'top': '',
'useHas': true
'useHas': true,
'useKeys': !!keys
};
// merge options into a template data object
@@ -579,14 +574,14 @@
// create the function factory
var factory = Function(
'hasOwnProperty, isArguments, isArray, isString, lodash, ' +
'objectTypes, nativeKeys',
'hasOwnProperty, isArguments, isArray, isString, keys, ' +
'lodash, objectTypes',
'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
);
// return the compiled function
return factory(
hasOwnProperty, isArguments, isArray, isString, lodash,
objectTypes, nativeKeys
hasOwnProperty, isArguments, isArray, isString, keys,
lodash, objectTypes
);
}
@@ -648,6 +643,53 @@
// no operation performed
}
/**
* A fallback implementation of `isPlainObject` that checks if a given `value`
* is an object created by the `Object` constructor, assuming objects created
* by the `Object` constructor have no inherited enumerable properties and that
* there are no `Object.prototype` extensions.
*
* @private
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
*/
function shimIsPlainObject(value) {
// avoid non-objects and false positives for `arguments` objects
var result = false;
if (!(value && toString.call(value) == objectClass)) {
return result;
}
// check that the constructor is `Object` (i.e. `Object instanceof Object`)
var ctor = value.constructor;
if ((!isFunction(ctor)) || ctor instanceof ctor) {
// In most environments an object's own properties are iterated before
// its inherited properties. If the last iterated property is an object's
// own property then there are no inherited enumerable properties.
forIn(value, function(value, key) {
result = key;
});
return result === false || hasOwnProperty.call(value, result);
}
return result;
}
/**
* A fallback implementation of `Object.keys` that produces an array of the
* given object's own enumerable property names.
*
* @private
* @type Function
* @param {Object} object The object to inspect.
* @returns {Array} Returns a new array of property names.
*/
var shimKeys = createIterator({
'args': 'object',
'init': '[]',
'top': 'if (!(objectTypes[typeof object])) return result',
'loop': 'result.push(index)',
'arrays': false
});
/**
* Slices the `collection` from the `start` index up to, but not including,
* the `end` index.
@@ -709,92 +751,6 @@
return toString.call(value) == argsClass;
}
/**
* This method is similar to `_.find`, except that it returns the key of the
* element that passes the callback check, instead of the element itself.
*
* @static
* @memberOf _
* @category Objects
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the key of the found element, else `undefined`.
* @example
*
* _.findKey({ 'a': 1, 'b': 2, 'c': 3, 'd': 4 }, function(num) { return num % 2 == 0; });
* // => 'b'
*/
function findKey(collection, callback, thisArg) {
var result;
callback = lodash.createCallback(callback, thisArg);
forOwn(collection, function(value, key, collection) {
if (callback(value, key, collection)) {
result = key;
return false;
}
});
return result;
}
/**
* Iterates over `object`'s own and inherited enumerable properties, executing
* the `callback` for each property. The `callback` is bound to `thisArg` and
* invoked with three arguments; (value, key, object). Callbacks may exit iteration
* early by explicitly returning `false`.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* function Dog(name) {
* this.name = name;
* }
*
* Dog.prototype.bark = function() {
* alert('Woof, woof!');
* };
*
* _.forIn(new Dog('Dagny'), function(value, key) {
* alert(key);
* });
* // => alerts 'name' and 'bark' (order is not guaranteed)
*/
var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {
'useHas': false
});
/**
* Iterates over an object's own enumerable properties, executing the `callback`
* for each property. The `callback` is bound to `thisArg` and invoked with three
* arguments; (value, key, object). Callbacks may exit iteration early by explicitly
* returning `false`.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
* alert(key);
* });
* // => alerts '0', '1', and 'length' (order is not guaranteed)
*/
var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
/**
* Checks if `value` is an array.
*
@@ -837,52 +793,6 @@
return nativeKeys(object);
};
/**
* A fallback implementation of `isPlainObject` that checks if a given `value`
* is an object created by the `Object` constructor, assuming objects created
* by the `Object` constructor have no inherited enumerable properties and that
* there are no `Object.prototype` extensions.
*
* @private
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
*/
function shimIsPlainObject(value) {
// avoid non-objects and false positives for `arguments` objects
var result = false;
if (!(value && toString.call(value) == objectClass)) {
return result;
}
// check that the constructor is `Object` (i.e. `Object instanceof Object`)
var ctor = value.constructor;
if ((!isFunction(ctor)) || ctor instanceof ctor) {
// In most environments an object's own properties are iterated before
// its inherited properties. If the last iterated property is an object's
// own property then there are no inherited enumerable properties.
forIn(value, function(value, key) {
result = key;
});
return result === false || hasOwnProperty.call(value, result);
}
return result;
}
/**
* A fallback implementation of `Object.keys` that produces an array of the
* given object's own enumerable property names.
*
* @private
* @param {Object} object The object to inspect.
* @returns {Array} Returns a new array of property names.
*/
function shimKeys(object) {
var result = [];
forOwn(object, function(value, key) {
result.push(key);
});
return result;
}
/**
* Used to convert characters to HTML entities:
*
@@ -1140,6 +1050,92 @@
*/
var defaults = createIterator(defaultsIteratorOptions);
/**
* This method is similar to `_.find`, except that it returns the key of the
* element that passes the callback check, instead of the element itself.
*
* @static
* @memberOf _
* @category Objects
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the key of the found element, else `undefined`.
* @example
*
* _.findKey({ 'a': 1, 'b': 2, 'c': 3, 'd': 4 }, function(num) { return num % 2 == 0; });
* // => 'b'
*/
function findKey(collection, callback, thisArg) {
var result;
callback = lodash.createCallback(callback, thisArg);
forOwn(collection, function(value, key, collection) {
if (callback(value, key, collection)) {
result = key;
return false;
}
});
return result;
}
/**
* Iterates over `object`'s own and inherited enumerable properties, executing
* the `callback` for each property. The `callback` is bound to `thisArg` and
* invoked with three arguments; (value, key, object). Callbacks may exit iteration
* early by explicitly returning `false`.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* function Dog(name) {
* this.name = name;
* }
*
* Dog.prototype.bark = function() {
* alert('Woof, woof!');
* };
*
* _.forIn(new Dog('Dagny'), function(value, key) {
* alert(key);
* });
* // => alerts 'name' and 'bark' (order is not guaranteed)
*/
var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, {
'useHas': false
});
/**
* Iterates over an object's own enumerable properties, executing the `callback`
* for each property. The `callback` is bound to `thisArg` and invoked with three
* arguments; (value, key, object). Callbacks may exit iteration early by explicitly
* returning `false`.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
* alert(key);
* });
* // => alerts '0', '1', and 'length' (order is not guaranteed)
*/
var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions);
/**
* Creates a sorted array of all enumerable properties, own and inherited,
* of `object` that have function values.