是否有一个通用的JavaScript函数来检查变量是否有值,并确保它不是未定义的或空的?我有这个代码,但我不确定它是否涵盖所有情况:

function isEmpty(val){
    return (val === undefined || val == null || val.length <= 0) ? true : false;
}

当前回答

你做得有点过头了。要检查变量是否没有给定值,只需要检查undefined和null。

function isEmpty(value){
    return (typeof value === "undefined" || value === null);
}

这是假设0、“”和对象(甚至是空对象和数组)是有效的“值”。

其他回答

真空度

我不建议尝试定义或使用计算整个世界中任何值是否为空的函数。“空”到底意味着什么?如果我让human={name:‘bob’,gast:‘empty’},isEmpty(human)是否应该返回true?如果我让reg=new RegExp('');,isEmpty(reg)是否应返回true?isEmpty([null,null,null,null])怎么样?这个列表只包含空,所以列表本身是空的吗?我想在这里提出一些关于javascript中的“真空性”(一个故意模糊的词,以避免预先存在的关联)的注释,并且我想指出,javascript值中的“空洞性”永远不应该被笼统地处理。


真实/虚假

为了决定如何确定值的“空洞性”,我们需要适应javascript内置的固有感觉,即值是“真实的”还是“虚假的”。自然,null和undefined都是“假的”。不那么自然的是,数字0(除了NaN之外没有其他数字)也是“假”的。最不自然的是:“”是假的,但[]和{}(以及new Set()和new Map())是真的——尽管它们看起来都一样空洞!


空与未定义

还有一些关于空和未定义的讨论——我们真的需要这两者来表达程序中的空洞吗?我个人避免在代码中出现undefined。我总是用null表示“空虚”。然而,我们再次需要适应javascript对null和undefined的区别的固有感觉:

尝试访问不存在的属性时,未定义调用函数时省略参数会导致该参数接收到未定义的:

设f=a=>a;控制台日志(f('hi'));console.log(f());

具有默认值的参数仅在给定未定义而非空时接收默认值:

设f=(v='hello')=>v;console.log(f(null));console.log(f(未定义));

对我来说,空是空虚的一个明确的能指;“本可以填写的内容故意留空”。

真正的undefined是一个必要的复杂因素,它允许一些js特性存在,但在我看来,它应该永远留在幕后;没有直接交互。例如,我们可以将undefined看作javascript实现默认函数参数的机制。如果不向函数提供参数,它将收到一个undefined值。如果函数参数最初设置为undefined,则默认值将应用于该参数。在这种情况下,undefined是默认函数参数的关键,但它仍停留在后台:我们可以实现默认参数功能,而无需引用undefined:

这是一个错误的默认参数实现,因为它直接与undefined交互:

let fnWithDefaults = arg => {
  if (arg === undefined) arg = 'default';
  ...
};

这是一个很好的实现:

let fnWithDefaults = (arg='default') => { ... };

这是接受默认参数的坏方法:

fnWithDefaults(undefined);

只需执行以下操作:

fnWithDefaults();

顺便问一下:您是否有一个具有多个参数的函数,并且您希望在接受其他参数的默认值的同时提供一些参数?

例如。:

let fnWithDefaults = (a=1, b=2, c=3, d=4) => console.log(a, b, c, d);

如果您想为a和d提供值并接受其他值的默认值,该怎么办?这似乎是错误的:

fnWithDefaults(10, undefined, undefined, 40);

答案是:重构fnWithDefaults以接受单个对象:

let fnWithDefaults = ({ a=1, b=2, c=3, d=4 }={}) => console.log(a, b, c, d);
fnWithDefaults({ a: 10, d: 40 }); // Now this looks really nice! (And never talks about "undefined")

非通用真空度

我认为,真空永远不应该以一种通用的方式来处理。相反,在确定数据是否空洞之前,我们应该始终严格获取有关数据的更多信息-我主要通过检查我处理的数据类型来做到这一点:

让isType=(value,Cls)=>{//有意使用松散比较运算符检测到`null`//和“undefined”,没有别的!返回值!=null&&Object.getPrototypeOf(值).cconstructor==Cls;};

注意,此函数忽略继承-它希望值是Cls的直接实例,而不是Cls子类的实例。我避免实例化的原因有两个:

([]instanceof Object)===true(“数组是一个对象”)(“”instanceof String)===false(“字符串不是字符串”)

注意,Object.getPrototypeOf用于避免(模糊的)边缘情况,例如let v={constructor:String};isType函数仍然正确返回isType(v,String)(false)和isType(v,Object)(true)。

总之,我建议使用isType函数以及以下提示:

最小化未知类型的代码处理值的数量。例如,对于v=JSON.parse(someRawValue);,我们的v变量现在是未知类型。我们应该尽早限制我们的可能性。最好的方法是要求特定类型:例如,如果(!isType(v,Array))抛出新错误(“预期数组”);-这是一种非常快速且富有表现力的方法,可以消除v的泛型性质,并确保它始终是一个数组。但有时,我们需要允许v具有多种类型。在这些情况下,我们应该尽早创建v不再通用的代码块:

if(isType(v,String)){/*v在这个块中不是通用的-它是一个字符串*/}否则如果(isType(v,Number)){/*v在这个块中不是通用的-它是一个数字*/}否则if(isType(v,Array)){/*v在这个块中不是通用的,它是一个数组*/}其他{抛出新错误(“预期的字符串、数字或数组”);}

始终使用“白名单”进行验证。如果您需要一个值,例如字符串、数字或数组,请检查这3种“白色”可能性,如果这3种可能性都不满足,则抛出错误。我们应该能够看到,检查“黑色”可能性不是很有用:假设我们写if(v==null)throw new Error('null value rejected');-这对于确保空值不通过非常有用,但是如果一个值通过了,我们仍然对它一无所知。通过这个空检查的值v仍然是非常通用的-它不是空!黑名单很难消除共性。除非值为空,否则不要考虑“空值”。相反,考虑“真空的X”。本质上,永远不要考虑做if(isEmpty(val)){/*…*/}-无论isEmpty函数是如何实现的(我不想知道…),它都没有意义!而且太普通了!真空度只能在了解val类型的情况下计算。真空度检查应如下所示:“字符串,无字符”:if(isType(val,String)&&val.length==0)。。。“一个对象,带0个道具”:if(isType(val,Object)&&Object.entries(val).length==0)。。。“数字,等于或小于零”:if(isType(val,number)&&val<=0)。。。“一个数组,没有项目”:if(isType(val,Array)&&val.length==0)。。。唯一的例外是使用null表示某些功能。在这种情况下,说“真空值”很有意义:如果(val==null)。。。

第一个评分最好的答案是错误的。若值未定义,则会在现代浏览器中引发异常。您必须使用:

if (typeof(value) !== "undefined" && value)

or

if (typeof value  !== "undefined" && value)

这还包括空数组和空对象

null,未定义,“”,0,[],{}

isEmpty = (value) => (!value  || (typeof v === 'object' &&
   Object.keys(value).length < 1));

仅使用“空值合并”检查未定义和空值

if ((myVariable ?? undefined) !== undefined) {
    // handle myVariable has a value, including 0 or ""
}
else {
    // handle undefined or null only
}

来自铬控制台

{const x=undefined; (x ?? undefined) !== undefined}
false

{const x=null; (x ?? undefined) !== undefined}
false

{const x=0; (x ?? undefined) !== undefined}
true

{const x=""; (x ?? undefined) !== undefined}
true

{const x={}; (x ?? undefined) !== undefined}
true

{const x=[]; (x ?? undefined) !== undefined}
true

{const x="a"; (x ?? undefined) !== undefined}
true

对于每一个有类似问题的人来说,以下内容非常有用,我在过去的几年里都把它放在了我的图书馆里:

(function(g3, $, window, document, undefined){
   g3.utils = g3.utils || {};
/********************************Function type()********************************
* Returns a lowercase string representation of an object's constructor.
* @module {g3.utils}
* @function {g3.utils.type}
* @public
* @param {Type} 'obj' is any type native, host or custom.
* @return {String} Returns a lowercase string representing the object's 
* constructor which is different from word 'object' if they are not custom.
* @reference http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
* http://stackoverflow.com/questions/3215046/differentiating-between-arrays-and-hashes-in-javascript
* http://javascript.info/tutorial/type-detection
*******************************************************************************/
g3.utils.type = function (obj){
   if(obj === null)
      return 'null';
   else if(typeof obj === 'undefined')
      return 'undefined';
   return Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1].toLowerCase();
};
}(window.g3 = window.g3 || {}, jQuery, window, document));