Хотя map
это правильное решение для выбора «столбцов» из списка объектов, у него есть и обратная сторона. Если явно не проверено, существуют ли столбцы, это выдаст ошибку и (в лучшем случае) предоставит вам undefined
. Я бы выбрал reduce
решение, которое может просто игнорировать свойство или даже установить значение по умолчанию.
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;
}, []);
}
пример jsbin
Это будет работать, даже если один из элементов в предоставленном списке не является объектом или не содержит поле.
Это может быть даже сделано более гибким путем согласования значения по умолчанию, если элемент не является объектом или не содержит поле.
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;
}, []);
}
пример jsbin
Это будет то же самое с картой, так как длина возвращаемого массива будет такой же, как предоставленный массив. (В этом случае a map
немного дешевле, чем 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;
}, []);
}
пример jsbin
Кроме того, существует наиболее гибкое решение, позволяющее переключаться между двумя вариантами поведения, просто предоставляя альтернативное значение.
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;
}, []);
}
пример jsbin
Поскольку вышеприведенные примеры (надеюсь) проливают некоторый свет на то, как это работает, давайте немного сократим функцию, используя Array.concat
функцию.
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 : []));
}, []);
}
пример jsbin
var foos = objArray.pluck("foo");
.