Sì, Array.map () o $ .map () fa la stessa cosa.
//array.map:
var ids = this.fruits.map(function(v){
return v.Id;
});
//jQuery.map:
var ids2 = $.map(this.fruits, function (v){
return v.Id;
});
console.log(ids, ids2);
http://jsfiddle.net/NsCXJ/1/
Dato che array.map non è supportato nei browser meno recenti, ti suggerisco di seguire il metodo jQuery.
Se preferisci l'altro per qualche motivo, puoi sempre aggiungere un polyfill per il vecchio supporto del browser.
Puoi sempre aggiungere metodi personalizzati anche al prototipo dell'array:
Array.prototype.select = function(expr){
var arr = this;
//do custom stuff
return arr.map(expr); //or $.map(expr);
};
var ids = this.fruits.select(function(v){
return v.Id;
});
Una versione estesa che utilizza la funzione di costruzione se si passa una stringa. Qualcosa con cui giocare forse:
Array.prototype.select = function(expr){
var arr = this;
switch(typeof expr){
case 'function':
return $.map(arr, expr);
break;
case 'string':
try{
var func = new Function(expr.split('.')[0],
'return ' + expr + ';');
return $.map(arr, func);
}catch(e){
return null;
}
break;
default:
throw new ReferenceError('expr not defined or not supported');
break;
}
};
console.log(fruits.select('x.Id'));
http://jsfiddle.net/aL85j/
Aggiornare:
Poiché questa è diventata una risposta così popolare, sto aggiungendo il mio where()
+ simile firstOrDefault()
. Questi potrebbero anche essere usati con l'approccio del costruttore di funzioni basato su stringhe (che è il più veloce), ma ecco un altro approccio che utilizza un oggetto letterale come filtro:
Array.prototype.where = function (filter) {
var collection = this;
switch(typeof filter) {
case 'function':
return $.grep(collection, filter);
case 'object':
for(var property in filter) {
if(!filter.hasOwnProperty(property))
continue; // ignore inherited properties
collection = $.grep(collection, function (item) {
return item[property] === filter[property];
});
}
return collection.slice(0); // copy the array
// (in case of empty object filter)
default:
throw new TypeError('func must be either a' +
'function or an object of properties and values to filter by');
}
};
Array.prototype.firstOrDefault = function(func){
return this.where(func)[0] || null;
};
Uso:
var persons = [{ name: 'foo', age: 1 }, { name: 'bar', age: 2 }];
// returns an array with one element:
var result1 = persons.where({ age: 1, name: 'foo' });
// returns the first matching item in the array, or null if no match
var result2 = persons.firstOrDefault({ age: 1, name: 'foo' });
Ecco un test jsperf per confrontare la funzione di costruzione della funzione con la velocità letterale dell'oggetto. Se decidi di utilizzare il primo, tieni presente di citare correttamente le stringhe.
La mia preferenza personale è quella di utilizzare le soluzioni letterali basate sull'oggetto quando si filtrano 1-2 proprietà e passare una funzione di callback per un filtro più complesso.
Concluderò con 2 suggerimenti generali quando si aggiungono metodi ai prototipi di oggetti nativi:
Verificare la presenza di metodi esistenti prima di sovrascrivere, ad esempio:
if(!Array.prototype.where) {
Array.prototype.where = ...
Se non è necessario supportare IE8 e versioni successive, definire i metodi utilizzando Object.defineProperty per renderli non enumerabili. Se qualcuno ha usato for..in
un array (che è sbagliato in primo luogo) itererà anche le proprietà enumerabili. Solo un avviso.