Почему `_.map` возвращает undefined, когда я возвращаю` false`?

У меня есть функция, которая отображает массив с underscore. Вот функция:

var services = _.map(userCopy.get('services'), function (service) {
    if (service.service_selected === true) {
        return service;
    }
});

Моя проблема в том, что когда conditional === false, я получаю undefined, помещенный в services. Конечно, я могу удалить undefined, но это уродливо, и я просто хочу правильно использовать map. Как это исправить?

Ответы

Ответ 1

_.map использует все, что возвращает функция, для построения результата. Если функция не возвращает ничего явно, JavaScript возвращает undefined. Поэтому результат _.map имеет undefined всякий раз, когда условие терпит неудачу.

Что вам действительно нужно, это _.filter

var services = _.filter(userCopy.get('services'), function(service) {
    return service.service_selected === true;
});

_.filter принимает коллекцию и функцию предиката. Он применяет функцию предиката к каждому значению коллекции, и если функция возвращает true, этот элемент будет включен в результат, если функция возвращает false, этот элемент будет пропущен.

Примечание. Фактически вы можете использовать _.matcher вместе с _.filter, как этот

var isServiceSelected = _.matcher({
    service_selected: true;
});

var services = _.filter(userCopy.get('services'), isServiceSelected);

Это будет очень полезно, если вы собираетесь фильтровать на основе условия service_selected: true более одного раза. Если это всего лишь одноразовая вещь, то _.where, показанная ниже, была бы лучшей альтернативой.


Вы также можете использовать _.where, который может возвращать объекты только в том случае, если текущий объект содержит все перечисленные пары ключей-значений, например это

var services = _.where(userCopy.get('services'), {
    service_selected: true;
});

Теперь будут возвращены все служебные объекты, значения атрибута service_selected как true.


Demo:

function display(heading, data) {
    var json = JSON.stringify(data, null, 4);
    document.body.appendChild(document.createElement('h3')).innerHTML = heading;
    document.body.appendChild(document.createElement('pre')).innerHTML = json;
}


var data = [{
    "name": "auth",
    "service_selected": true
}, {
    "name": "authorization",
    "service_selected": false
}, {
    "name": "faltu",
    "service_selected": true
}];


display("_.filter", _.filter(data, function (service) {
    return service.service_selected === true;
}));

display("_.matcher", _.filter(data, _.matcher({
    service_selected: true
})));

display("_.where", _.where(data, {
    service_selected: true
}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Ответ 2

Обновлен мой ответ... Это решило мою проблему

    var missingParamsArray = _.map(requiredParams, function (val, param) {
        if (val) {
            if (!req.user[param]) {
                return param;
            }
        }
    });

    var missingParams = _.filter(missingParamsArray, Boolean);

missingParams также можно записать как

var missingParams = _.filter(missingParamsArray, function (param) {
       return param !== undefined;
    });