当我们的代码本质上为空时,在特定情况下可能意味着以下任何一种情况;
- 0 表示数值
- 0.0 作为浮点值
- 字符串值中的'0'
- '0.0' 作为字符串值
- null 与 Null 值一样,它也可能捕获 undefined,也可能不会捕获
- 未定义为未定义值
- false 为 false 真实值,根据机会 0 也为真实值,但如果我们想捕获 false 的原样怎么办
- '' 没有空格或制表符的空字符串值
- ' ' 字符串,只有空格或制表符
在现实生活中,正如 OP 所说,我们可能希望全部测试它们,或者有时我们可能只想测试有限的一组条件。
通常if(!a){return true;} 在大多数情况下都能发挥作用,但它不会涵盖更广泛的条件。
另一个成功的黑客是return (!value || value == undefined || value == "" || value.length == 0);
但是如果我们需要控制整个过程呢?
在原生核心 JavaScript 中没有简单的鞭打解决方案,它必须被采用。考虑到我们放弃了对旧版 IE11 的支持(老实说,即使是 Windows,我们也应该如此)低于所有现代浏览器中因受挫而诞生的解决方案;
function empty (a,b=[])
{if(!Array.isArray(b)) return;
var conditions=[null,'0','0.0',false,undefined,''].filter(x => !b.includes(x));
if(conditions.includes(a)|| (typeof a === 'string' && conditions.includes(a.toString().trim())))
{return true;};
return false;};`
解决方案背后的逻辑是函数有两个参数a和b,a是我们需要检查的值,b是我们需要排除的具有设定条件的数组上面列出的预定义条件。 b 的默认值设置为空数组 []。
函数的第一次运行是检查b是否为数组,如果不是则提前退出函数。
下一步是计算 [null,'0','0.0',false,undefined,''] 和数组 b 的数组差异。如果 b 是空数组,则预定义条件将成立,否则它将删除匹配值。
条件 = [预定义集] - [待排除集]
filter 函数正是利用它。
现在我们在数组集合中有条件,我们需要做的就是检查值是否在条件数组中。
includes 函数正是这样做的,无需自己编写讨厌的循环,让 JS 引擎完成繁重的工作。
问题
如果我们要将 a 转换为字符串进行比较,那么 0 和 0.0 可以正常运行,但是 Null 和 Undefined 会通过错误阻塞整个脚本。我们需要边缘案例解决方案。如果第一个条件不满足,下面简单的 || 涵盖了边缘情况。如果未满足,则通过 include 运行另一个早期检查会提前退出。
if(conditions.includes(a)|| (['string', 'number'].includes(typeof a) && conditions.includes(a.toString().trim())))
trim() 函数将覆盖更广泛的空白和仅制表符的值,并且只会在极端情况下发挥作用。
游乐场
function empty (a,b=[]){
if(!Array.isArray(b)) return;
conditions=[null,'0','0.0',false,undefined,''].filter(x => !b.includes(x));
if(conditions.includes(a)||
(['string', 'number'].includes(typeof a) && conditions.includes(a.toString().trim()))){
return true;
}
return false;
}
console.log('1 '+empty());
console.log('2 '+empty(''));
console.log('3 '+empty(' '));
console.log('4 '+empty(0));
console.log('5 '+empty('0'));
console.log('6 '+empty(0.0));
console.log('7 '+empty('0.0'));
console.log('8 '+empty(false));
console.log('9 '+empty(null));
console.log('10 '+empty(null,[null]));
console.log('11 dont check 0 as number '+empty(0,['0']));
console.log('12 dont check 0 as string '+empty('0',['0']));
console.log('13 as number for false as value'+empty(false,[false]));
让我们让它变得复杂——如果我们要比较的值是数组它的自身,并且可以嵌套得尽可能深。如果我们要检查数组中的任何值是否为空怎么办,这可能是一个边缘业务案例。
function empty (a,b=[]){
if(!Array.isArray(b)) return;
conditions=[null,'0','0.0',false,undefined,''].filter(x => !b.includes(x));
if(Array.isArray(a) && a.length > 0){
for (i = 0; i < a.length; i++) { if (empty(a[i],b))return true;}
}
if(conditions.includes(a)||
(['string', 'number'].includes(typeof a) && conditions.includes(a.toString().trim()))){
return true;
}
return false;
}
console.log('checking for all values '+empty([1,[0]]));
console.log('excluding for 0 from condition '+empty([1,[0]], ['0']));
我在我的框架中采用的简单且更广泛的用例功能;
- 控制在给定情况下空的确切定义是什么
- 允许重新定义空的条件
- 几乎可以比较字符串、数字、浮点数、truthy、null、未定义和深度数组中的所有内容
- 在制定解决方案时要牢记可重复性和灵活性。如果要处理简单的一两个案例,所有其他答案都适用。但是,总是存在这样的情况,即在 sn-ps 上进行编码时定义的空更改在这种情况下可以完美地工作。