为何Lodash的forEach返回false无法终止迭代?函数始终返回true排查
问题描述
我有一个对象,想要检查该对象的任意属性中是否包含有效值,但编写的函数始终返回true,找不到问题所在。相关代码如下:
function isResponsiblePersonEmpty() { const copyResponsiblePerson ={ "resonsiblePersonOne": [ { "uuid": "8120BC66-4BC9-4886-820E-8A9FE488F8F7", "name": "test", "company": "test", "availabilityGSMR": "test", "availabilityMobile": "test", "availabilityLandline": "", "availabilityPhoneInternal": "", "availabilityPhoneFallback": "" }, { "uuid": "BFE3B5AA-A61D-46B7-99A6-EC4CA2CDC0BF", "name": "test1", "company": "", "availabilityGSMR": "test1", "availabilityMobile": "", "availabilityLandline": "test1", "availabilityPhoneInternal": "", "availabilityPhoneFallback": "" } ], "resonsiblePersonTwo": [ { "uuid": "0414F81E-7F81-468D-BF1B-B1FA8FC34563", "name": "test3", "company": "", "availabilityGSMR": "", "availabilityMobile": "", "availabilityLandline": "", "availabilityPhoneInternal": "", "availabilityPhoneFallback": "" } ], "resonsiblePersonFour": null, "resonsiblePersonThree": null } const flatResponsiblePersonObj = _.flatMapDeep(copyResponsiblePerson); _.forEach(flatResponsiblePersonObj, (value, key)=> { // if any boolen value set to true, therefore responsible form filed is not empty if (value !== null) { return false; } if (value.uuid) {delete value.uuid } if( _.isObject(value)) { if(!_.isEmpty(value)) { return false; } } }); return true; } // Deep copy var isEmpty = isResponsiblePersonEmpty(); console.log(isEmpty)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>
问题分析
_.forEach的return逻辑误解:你以为在_.forEach回调里return false能让外层函数直接返回?不对!_.forEach的回调返回false只会跳过当前迭代项,不会终止整个循环,更不会让isResponsiblePersonEmpty函数提前返回。所以不管回调里怎么return,最后都会执行到return true,这是函数始终返回true的核心原因。- 逻辑顺序混乱:代码开头就判断
value !== null就return false,第一个元素是对象(非null),直接触发return,但forEach会继续遍历后续元素,最后还是返回true。而且这个判断逻辑本身错误——null是无效值,但非null的对象可能包含有效值也可能不包含,不能直接判定为“非空”。 - 无效值处理缺失:就算走到
_.isEmpty判断,包含空字符串的对象也会被_.isEmpty视为非空,但空字符串属于无效值,需要先过滤这类值再判断。
修正方案
换用_.some来实现遍历(该方法会在回调返回true时立即终止遍历,完美匹配“找是否存在有效值”的需求),同时优化有效值判断逻辑:
function isResponsiblePersonEmpty() { const copyResponsiblePerson ={ "resonsiblePersonOne": [ { "uuid": "8120BC66-4BC9-4886-820E-8A9FE488F8F7", "name": "test", "company": "test", "availabilityGSMR": "test", "availabilityMobile": "test", "availabilityLandline": "", "availabilityPhoneInternal": "", "availabilityPhoneFallback": "" }, { "uuid": "BFE3B5AA-A61D-46B7-99A6-EC4CA2CDC0BF", "name": "test1", "company": "", "availabilityGSMR": "test1", "availabilityMobile": "", "availabilityLandline": "test1", "availabilityPhoneInternal": "", "availabilityPhoneFallback": "" } ], "resonsiblePersonTwo": [ { "uuid": "0414F81E-7F81-468D-BF1B-B1FA8FC34563", "name": "test3", "company": "", "availabilityGSMR": "", "availabilityMobile": "", "availabilityLandline": "", "availabilityPhoneInternal": "", "availabilityPhoneFallback": "" } ], "resonsiblePersonFour": null, "resonsiblePersonThree": null } // 扁平化所有嵌套内容,同时过滤null值 const flatItems = _.flatMapDeep(copyResponsiblePerson, item => item !== null ? item : []); // 检查是否存在含有效值的对象 const hasValidValues = _.some(flatItems, item => { // 移除uuid字段 const { uuid, ...restProps } = item; // 检查剩余属性中是否有非空字符串(trim处理排除纯空格) return _.some(restProps, val => typeof val === 'string' && val.trim() !== ''); }); // 符合函数语义:有有效值则返回false(非空),无有效值返回true(空) return !hasValidValues; } var isEmpty = isResponsiblePersonEmpty(); console.log(isEmpty); // 输出false,因为存在有效值
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>
关键改进点
- 用
_.flatMapDeep时过滤null值,避免后续无效判断 - 替换
_.forEach为_.some,精准实现“找到有效值就终止”的逻辑,效率更高 - 先移除uuid字段,再检查剩余属性是否存在非空字符串(包含纯空格过滤)
- 返回值贴合函数名语义,逻辑更清晰
内容的提问来源于stack exchange,提问作者ShadaMon
相关产品推荐
相关产品推荐

