为什么当我返回`false`时,`_.map`会返回`undefined`?

18

我有一个函数,用underscore映射数组。以下是该函数:

var services = _.map(userCopy.get('services'), function (service) {
    if (service.service_selected === true) {
        return service;
    }
});
我的问题是当条件conditional === false时,services会接收到undefined。当然我可以去掉undefined,但那很丑陋,我只想正确使用map。我该如何解决这个问题?

因为如果 conditional === false,JavaScript 解释器将不会找到任何结构并转到隐式返回语句,该语句返回 undefined - http://shamansir.github.io/JavaScript-Garden/en/#core.undefined - 要返回 false,必须显式地这样做。 - Andrei Shostik
2个回答

37

_.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 的服务对象将被返回。

演示:

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>


然而,当迭代对象时,filter返回整个对象...而不是_.map()允许仅返回一个属性。 - doublejosh
@doublejosh 正确,但是OP想要整个service对象。我提供了一个使用_.where的替代方案,请查看。 - thefourtheye
你也可以快速地这样滚动一些东西:var missingParams = _.filter(missingParamsArray, Boolean); - Cmag

1
更新了我的答案...这解决了我的问题。
    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;
    });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接