From 42637b5880f040e8ce48ff7de758d2274919ffb8 Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Thu, 29 Oct 2009 10:46:53 -0400 Subject: [PATCH] Issue #2 -- each now calls iterator with (value, key, list) when iterating over javascript objects --- index.html | 7 +++---- test/collections.js | 4 ++-- underscore.js | 24 +++++++++++++----------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/index.html b/index.html index f032259a6..33716be85 100644 --- a/index.html +++ b/index.html @@ -171,10 +171,9 @@
Iterates over a list of elements, yielding each in turn to an iterator function. The iterator is bound to the context object, if one is - passed. Each invocation of iterator is called with three arguments, - element, index, and the list. - If list is a JavaScript object, a pair with key - and value properties will be yielded. If the list has an each + passed. Each invocation of iterator is called with three arguments: + (element, index, list). If list is a JavaScript object, iterator's + arguments will be (value, key, list). If the list has an each method of its own, it will be used instead. Delegates to the native forEach function if it exists.

diff --git a/test/collections.js b/test/collections.js index 69fe9ec47..3ef2ccba3 100644 --- a/test/collections.js +++ b/test/collections.js @@ -26,7 +26,7 @@ $(document).ready(function() { answers = []; var obj = {one : 1, two : 2, three : 3}; obj.constructor.prototype.four = 4; - _.each(obj, function(pair){ answers.push(pair.key); }); + _.each(obj, function(value, key){ answers.push(key); }); equals(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.'); delete obj.constructor.prototype.four; @@ -136,7 +136,7 @@ $(document).ready(function() { ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array'); var numbers = _.toArray({one : 1, two : 2, three : 3}); - equals(_.pluck(numbers, '0').join(', '), 'one, two, three', 'object flattened into array'); + equals(numbers.join(', '), '1, 2, 3', 'object flattened into array'); }); test('collections: size', function() { diff --git a/underscore.js b/underscore.js index 90cafc284..f9c642062 100644 --- a/underscore.js +++ b/underscore.js @@ -42,12 +42,8 @@ } else if (obj.each) { obj.each(function(value) { iterator.call(context, value, index++, obj); }); } else { - var i = 0; for (var key in obj) if (Object.prototype.hasOwnProperty.call(obj, key)) { - var value = obj[key], pair = [key, value]; - pair.key = key; - pair.value = value; - iterator.call(context, pair, i++, obj); + iterator.call(context, obj[key], key, obj); } } } catch(e) { @@ -61,8 +57,8 @@ _.map = function(obj, iterator, context) { if (obj && obj.map) return obj.map(iterator, context); var results = []; - _.each(obj, function(value, index) { - results.push(iterator.call(context, value, index)); + _.each(obj, function(value, index, list) { + results.push(iterator.call(context, value, index, list)); }); return results; }; @@ -137,8 +133,8 @@ _.include = function(obj, target) { if (_.isArray(obj)) return _.indexOf(obj, target) != -1; var found = false; - _.each(obj, function(pair) { - if (found = pair.value === target) { + _.each(obj, function(value) { + if (found = value === target) { throw '__break__'; } }); @@ -361,12 +357,18 @@ // Retrieve the names of an object's properties. _.keys = function(obj) { - return _.pluck(obj, 'key'); + return _.reduce(obj, [], function(memo, value, key) { + memo.push(key); + return memo; + }); }; // Retrieve the values of an object's properties. _.values = function(obj) { - return _.pluck(obj, 'value'); + return _.reduce(obj, [], function(memo, value) { + memo.push(value); + return memo; + }); }; // Extend a given object with all of the properties in a source object.