如何递归判断JS对象/数组仅包含自定义假值?
递归判断对象/数组仅包含自定义空值(函数式实现)
自定义空值定义
我们将以下JS值定义为自定义空值:
""(空字符串)0(包含0.0、-0等所有零的变体)false(布尔值)[](空数组){}(空对象)
需求与示例
需要实现一个递归函数,判断目标对象或数组是否仅包含上述自定义空值(对象仅校验叶子节点值),示例如下:
- 符合条件(返回
true):{"x": 0}{"x": {"y": [0,0,[]]}}[0,0,[],{}][[[]], [], {}]
- 不符合条件(返回
false):[1]
现有代码问题分析
你提供的代码存在几个关键问题:
- 依赖全局变量
arr,多次调用会被污染,无法复用 - 使用
for...of遍历普通对象会失效,无法获取对象属性值 - 未处理
null(typeof null === 'object',但不属于自定义空值) - 未直接返回判断结果,需要额外处理数组,不符合函数式风格
函数式解决方案
下面是符合函数式风格的纯函数实现,核心思路是递归遍历+高阶函数校验,无副作用且逻辑清晰:
1. 辅助函数:判断单个值是否为自定义空值
const isCustomFalsy = (val) => { // 单独处理空数组:数组长度为0 if (Array.isArray(val)) return val.length === 0; // 单独处理空对象:自身不是null且属性数量为0 if (val && typeof val === 'object') return Object.keys(val).length === 0; // 处理原始类型:空字符串、false、所有零变体 return val === '' || val === false || val === 0; };
注:
val === 0会自动匹配0.0、-0等所有零的变体,因为JS中这些值与0严格相等。
2. 主递归函数:校验所有元素均为自定义空值
const isAllCustomFalsy = (val) => { // 当前值本身就是自定义空值,直接返回true if (isCustomFalsy(val)) return true; // 处理数组:递归校验每个元素,所有元素都符合才返回true if (Array.isArray(val)) { return val.every(isAllCustomFalsy); } // 处理普通对象:遍历所有属性值递归校验,全部符合才返回true if (val && typeof val === 'object') { return Object.values(val).every(isAllCustomFalsy); } // 其他非自定义空值的原始类型,直接返回false return false; };
3. 测试验证
// 测试示例 console.log(isAllCustomFalsy({"x": 0})); // true console.log(isAllCustomFalsy({"x": {"y": [0,0,[]]}})); // true console.log(isAllCustomFalsy([0,0,[],{}])); // true console.log(isAllCustomFalsy([[[]], [], {}])); // true console.log(isAllCustomFalsy([1])); // false
方案优势
- 纯函数设计:不依赖外部变量,输入决定输出,可安全复用
- 函数式风格:使用
every高阶函数简化遍历校验逻辑,代码简洁易读 - 边界处理:自动排除
null,正确处理数组和对象的遍历需求 - 递归逻辑清晰:先判断当前值,再递归处理子元素,层级分明
内容的提问来源于stack exchange,提问作者David542
相关产品推荐
相关产品推荐

