Chociaż map
jest właściwym rozwiązaniem do wybierania „kolumn” z listy obiektów, ma jednak pewną wadę. Jeśli nie zostanie wyraźnie zaznaczone, czy kolumny istnieją, wygeneruje błąd i (co najwyżej) zapewni undefined
. Wybrałbym reduce
rozwiązanie, które może po prostu zignorować właściwość lub nawet ustawić dla ciebie wartość domyślną.
function getFields(list, field) {
// reduce the provided list to an array only containing the requested field
return list.reduce(function(carry, item) {
// check if the item is actually an object and does contain the field
if (typeof item === 'object' && field in item) {
carry.push(item[field]);
}
// return the 'carry' (which is the list of matched field values)
return carry;
}, []);
}
przykład jsbin
Działa to nawet wtedy, gdy jeden z elementów na podanej liście nie jest obiektem lub nie zawiera pola.
Można go nawet uelastycznić, negocjując wartość domyślną, jeśli element nie jest obiektem lub nie zawiera pola.
function getFields(list, field, otherwise) {
// reduce the provided list to an array containing either the requested field or the alternative value
return list.reduce(function(carry, item) {
// If item is an object and contains the field, add its value and the value of otherwise if not
carry.push(typeof item === 'object' && field in item ? item[field] : otherwise);
// return the 'carry' (which is the list of matched field values)
return carry;
}, []);
}
przykład jsbin
Tak samo byłoby z mapą, ponieważ długość zwróconej tablicy byłaby taka sama jak dostarczonej tablicy. (W takim przypadku a map
jest nieco tańsze niż a reduce
):
function getFields(list, field, otherwise) {
// map the provided list to an array containing either the requested field or the alternative value
return list.map(function(item) {
// If item is an object and contains the field, add its value and the value of otherwise if not
return typeof item === 'object' && field in item ? item[field] : otherwise;
}, []);
}
przykład jsbin
A potem jest najbardziej elastyczne rozwiązanie, które pozwala przełączać się między oboma zachowaniami, po prostu zapewniając alternatywną wartość.
function getFields(list, field, otherwise) {
// determine once whether or not to use the 'otherwise'
var alt = typeof otherwise !== 'undefined';
// reduce the provided list to an array only containing the requested field
return list.reduce(function(carry, item) {
// If item is an object and contains the field, add its value and the value of 'otherwise' if it was provided
if (typeof item === 'object' && field in item) {
carry.push(item[field]);
}
else if (alt) {
carry.push(otherwise);
}
// return the 'carry' (which is the list of matched field values)
return carry;
}, []);
}
przykład jsbin
Ponieważ powyższe przykłady (mam nadzieję) rzuciły nieco światła na sposób, w jaki to działa, pozwólmy nieco skrócić tę funkcję, korzystając z tej Array.concat
funkcji.
function getFields(list, field, otherwise) {
var alt = typeof otherwise !== 'undefined';
return list.reduce(function(carry, item) {
return carry.concat(typeof item === 'object' && field in item ? item[field] : (alt ? otherwise : []));
}, []);
}
przykład jsbin
var foos = objArray.pluck("foo");
.