有没有可能在 Underscore.js 中获得正在排序的索引?

我使用的是 JS 库 下划线,特别是使用了 译自: 美国《科学》杂志网站(http://underscorejs.org/# each)翻译: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校库调用。我想知道是否有任何可能的方法来获取迭代器委托中值的索引

_.sortBy([1, 4, 2, 66, 444, 9], function(num){
/*It'd be great to have access to the index in here */
return Math.sin(num);
});
115782 次浏览

The iterator of _.each is called with 3 parameters (element, index, list). So yes, for _.each you cab get the index.

You can do the same in sortBy

Index is actually available like;

_.sortBy([1, 4, 2, 66, 444, 9], function(num, index){  });

You can get the index of the current iteration by adding another parameter to your iterator function, e.g.

_.each(['foo', 'bar', 'baz'], function (val, i) {
console.log(i + ": " + val); // 0: foo, 1: bar, 2: baz
});

More generally, under most circumstances, underscore functions that take a list and argument as the first two arguments, provide access to the list index as the next to last argument to the iterator. This is an important distinction when it comes to the two underscore functions, _.reduce and _.reduceRight, that take 'memo' as their third argument -- in the case of these two the index will not be the second argument, but the third:

var destination = (function() {
var fields = ['_333st', 'offroad', 'fbi'];
return _.reduce(waybillInfo.destination.split(','), function(destination, segment, index) {
destination[fields[index]] = segment;
return destination;
}, {});
})();


console.log(destination);
/*
_333st: "NYARFTW  TX"
fbi: "FTWUP"
offroad: "UP"


The following is better of course but not demonstrate my point:
var destination = _.object(['_333st', 'offroad', 'fbi'], waybillInfo.destination.split(','));
*/

So if you wanted you could get the index using underscore itself: _.last(_.initial(arguments)). A possible exception (I haven't tried) is _.map, as it can take an object instead of a list: "If list is a JavaScript object, iterator's arguments will be (value, key, list)." -- see: http://underscorejs.org/#map

If you'd rather transform your array, then the iterator parameter of underscore's map function is also passed the index as a second argument. So:

_.map([1, 4, 2, 66, 444, 9], function(value, index){ return index + ':' + value; });

... returns:

["0:1", "1:4", "2:2", "3:66", "4:444", "5:9"]

I think it's worth mentioning how the Underscore's _.each() works internally. The _.each(list, iteratee) checks if the passed list is an array object, or an object.

In the case that the list is an array, iteratee arguments will be a list element and index as in the following example:

var a = ['I', 'like', 'pancakes', 'a', 'lot', '.'];
_.each( a, function(v, k) { console.log( k + " " + v); });


0 I
1 like
2 pancakes
3 a
4 lot
5 .

On the other hand, if the list argument is an object the iteratee will take a list element and a key:

var o = {name: 'mike', lastname: 'doe', age: 21};
_.each( o, function(v, k) { console.log( k + " " + v); });


name mike
lastname doe
age 21

For reference this is the _.each() code from Underscore.js 1.8.3

_.each = _.forEach = function(obj, iteratee, context) {
iteratee = optimizeCb(iteratee, context);
var i, length;
if (isArrayLike(obj)) {
for (i = 0, length = obj.length; i < length; i++) {
iteratee(obj[i], i, obj);
}
} else {
var keys = _.keys(obj);
for (i = 0, length = keys.length; i < length; i++) {
iteratee(obj[keys[i]], keys[i], obj);
}
}
return obj;
};

When available, I believe that most lodash array functions will show the iteration. But sorting isn't really an iteration in the same way: when you're on the number 66, you aren't processing the fourth item in the array until it's finished. A custom sort function will loop through an array a number of times, nudging adjacent numbers forward or backward, until the everything is in its proper place.