mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-08 10:17:48 +00:00
Issue #70 -- implementing each, find, all, any, etc. without the use of a try/catch/throw. Minor speedup + avoids destroying the stack trace.
This commit is contained in:
@@ -7,10 +7,6 @@ $(document).ready(function() {
|
|||||||
equals(num, i + 1, 'each iterators provide value and iteration count');
|
equals(num, i + 1, 'each iterators provide value and iteration count');
|
||||||
});
|
});
|
||||||
|
|
||||||
var answer = null;
|
|
||||||
_.each([1, 2, 3], function(num){ if ((answer = num) == 2) _.breakLoop(); });
|
|
||||||
equals(answer, 2, 'the loop broke in the middle');
|
|
||||||
|
|
||||||
var answers = [];
|
var answers = [];
|
||||||
_.each([1, 2, 3], function(num){ answers.push(num * this.multiplier);}, {multiplier : 5});
|
_.each([1, 2, 3], function(num){ answers.push(num * this.multiplier);}, {multiplier : 5});
|
||||||
equals(answers.join(', '), '5, 10, 15', 'context object property accessed');
|
equals(answers.join(', '), '5, 10, 15', 'context object property accessed');
|
||||||
|
|||||||
@@ -15,15 +15,6 @@ $(document).ready(function() {
|
|||||||
equals(_.identity(moe), moe, 'moe is the same as his identity');
|
equals(_.identity(moe), moe, 'moe is the same as his identity');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('utility: breakLoop', function() {
|
|
||||||
var result = null;
|
|
||||||
_([1,2,3,4,5,6]).each(function(num) {
|
|
||||||
result = num;
|
|
||||||
if (num == 3) _.breakLoop();
|
|
||||||
});
|
|
||||||
equals(result, 3, 'broke out of a loop');
|
|
||||||
});
|
|
||||||
|
|
||||||
test("utility: uniqueId", function() {
|
test("utility: uniqueId", function() {
|
||||||
var ids = [], i = 0;
|
var ids = [], i = 0;
|
||||||
while(i++ < 100) ids.push(_.uniqueId());
|
while(i++ < 100) ids.push(_.uniqueId());
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
// Save the previous value of the `_` variable.
|
// Save the previous value of the `_` variable.
|
||||||
var previousUnderscore = root._;
|
var previousUnderscore = root._;
|
||||||
|
|
||||||
// Establish the object that gets thrown to break out of a loop iteration.
|
// Establish the object that gets returned to break out of a loop iteration.
|
||||||
var breaker = typeof StopIteration !== 'undefined' ? StopIteration : '__break__';
|
var breaker = {};
|
||||||
|
|
||||||
// Save bytes in the minified (but not gzipped) version:
|
// Save bytes in the minified (but not gzipped) version:
|
||||||
var ArrayProto = Array.prototype, ObjProto = Object.prototype;
|
var ArrayProto = Array.prototype, ObjProto = Object.prototype;
|
||||||
@@ -67,20 +67,20 @@
|
|||||||
// Handles objects implementing `forEach`, arrays, and raw objects.
|
// Handles objects implementing `forEach`, arrays, and raw objects.
|
||||||
// Delegates to **ECMAScript 5**'s native `forEach` if available.
|
// Delegates to **ECMAScript 5**'s native `forEach` if available.
|
||||||
var each = _.each = _.forEach = function(obj, iterator, context) {
|
var each = _.each = _.forEach = function(obj, iterator, context) {
|
||||||
try {
|
var value;
|
||||||
if (nativeForEach && obj.forEach === nativeForEach) {
|
if (nativeForEach && obj.forEach === nativeForEach) {
|
||||||
obj.forEach(iterator, context);
|
obj.forEach(iterator, context);
|
||||||
} else if (_.isNumber(obj.length)) {
|
} else if (_.isNumber(obj.length)) {
|
||||||
for (var i = 0, l = obj.length; i < l; i++) iterator.call(context, obj[i], i, obj);
|
for (var i = 0, l = obj.length; i < l; i++) {
|
||||||
} else {
|
if (iterator.call(context, obj[i], i, obj) === breaker) return;
|
||||||
for (var key in obj) {
|
}
|
||||||
if (hasOwnProperty.call(obj, key)) iterator.call(context, obj[key], key, obj);
|
} else {
|
||||||
|
for (var key in obj) {
|
||||||
|
if (hasOwnProperty.call(obj, key)) {
|
||||||
|
if (iterator.call(context, obj[key], key, obj) === breaker) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(e) {
|
|
||||||
if (e != breaker) throw e;
|
|
||||||
}
|
}
|
||||||
return obj;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the results of applying the iterator to each element.
|
// Return the results of applying the iterator to each element.
|
||||||
@@ -126,10 +126,10 @@
|
|||||||
// Return the first value which passes a truth test. Aliased as `detect`.
|
// Return the first value which passes a truth test. Aliased as `detect`.
|
||||||
_.find = _.detect = function(obj, iterator, context) {
|
_.find = _.detect = function(obj, iterator, context) {
|
||||||
var result;
|
var result;
|
||||||
each(obj, function(value, index, list) {
|
any(obj, function(value, index, list) {
|
||||||
if (iterator.call(context, value, index, list)) {
|
if (iterator.call(context, value, index, list)) {
|
||||||
result = value;
|
result = value;
|
||||||
_.breakLoop();
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
@@ -164,7 +164,7 @@
|
|||||||
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
|
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
|
||||||
var result = true;
|
var result = true;
|
||||||
each(obj, function(value, index, list) {
|
each(obj, function(value, index, list) {
|
||||||
if (!(result = result && iterator.call(context, value, index, list))) _.breakLoop();
|
if (!(result = result && iterator.call(context, value, index, list))) return breaker;
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
@@ -172,12 +172,12 @@
|
|||||||
// Determine if at least one element in the object matches a truth test.
|
// Determine if at least one element in the object matches a truth test.
|
||||||
// Delegates to **ECMAScript 5**'s native `some` if available.
|
// Delegates to **ECMAScript 5**'s native `some` if available.
|
||||||
// Aliased as `any`.
|
// Aliased as `any`.
|
||||||
_.some = _.any = function(obj, iterator, context) {
|
var any = _.some = _.any = function(obj, iterator, context) {
|
||||||
iterator = iterator || _.identity;
|
iterator = iterator || _.identity;
|
||||||
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
|
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
|
||||||
var result = false;
|
var result = false;
|
||||||
each(obj, function(value, index, list) {
|
each(obj, function(value, index, list) {
|
||||||
if (result = iterator.call(context, value, index, list)) _.breakLoop();
|
if (result = iterator.call(context, value, index, list)) return breaker;
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
@@ -187,8 +187,8 @@
|
|||||||
_.include = _.contains = function(obj, target) {
|
_.include = _.contains = function(obj, target) {
|
||||||
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
||||||
var found = false;
|
var found = false;
|
||||||
each(obj, function(value) {
|
any(obj, function(value) {
|
||||||
if (found = value === target) _.breakLoop();
|
if (found = value === target) return true;
|
||||||
});
|
});
|
||||||
return found;
|
return found;
|
||||||
};
|
};
|
||||||
@@ -642,11 +642,6 @@
|
|||||||
for (var i = 0; i < n; i++) iterator.call(context, i);
|
for (var i = 0; i < n; i++) iterator.call(context, i);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Break out of the middle of an iteration.
|
|
||||||
_.breakLoop = function() {
|
|
||||||
throw breaker;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add your own custom functions to the Underscore object, ensuring that
|
// Add your own custom functions to the Underscore object, ensuring that
|
||||||
// they're correctly added to the OOP wrapper as well.
|
// they're correctly added to the OOP wrapper as well.
|
||||||
_.mixin = function(obj) {
|
_.mixin = function(obj) {
|
||||||
|
|||||||
Reference in New Issue
Block a user