如何在JavaScript中检查空/未定义/空字符串?

3976
在 JavaScript 中是否有类似于 string.Empty 的方法,或者只需要检查 "" 是否为空?

5
仅供参考,我认为String类最有用的API在Mozillajavascript kit上。elated.com提供了关于String所有属性、方法的教程...请注意:Mozilla链接已更新为https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String。 - Gene T
2
如果需求明确指定,那将会非常有帮助。isEmpty 应该在什么情况下返回 true?检查 "" 暗示它只应在值为字符串类型且长度为 0 时返回 true。这里的许多答案都假设它也应该对某些或所有 falsy 值返回 true。 - RobG
str.length > -1 - Omar bakhsh
我完全同意@RobG的观点,这个问题定义得很糟糕。你为什么会认为nullundefined是空的呢?一个空字符串就是一个空字符串,它不是nullundefined - Flimm
@GeneT的链接已经失效,这里提供Mozilla参考文档的更新链接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String - randy
显示剩余2条评论
54个回答

4890

空字符串,未定义,null等

要检查真实值

if (strValue) {
    // strValue was non-empty string, true, 42, Infinity, [], ...
}

检查 假值

if (!strValue) {
    // strValue was empty string, false, 0, null, undefined, ...
}

仅限空字符串

要检查是否为仅限空字符串,使用=== 运算符进行严格相等性比较:""

if (strValue === "") {
    // strValue was empty string
}

要严格检查非空字符串,请使用!== 操作符

if (strValue !== "") {
    // strValue was not an empty string
}

278
测试字符串的长度属性可能比将字符串与""进行比较更快,因为解释器不需要从字符串文字创建一个String对象。 - Vincent Robert
78
在Chrome开发者工具中进行一些简单的性能分析,测试=== ''.length之间的区别并未显示出明显的改进(并且仅在您可以假设有一个字符串的情况下使用.length才有效)。 - bdukes
46
当你开始关注这种微小的优化时,我认为Chrome并不是你在性能问题方面遇到最多困难的浏览器... - Vincent Robert
40
请注意,如果您对“空字符串”的定义包括空格,则此解决方案不适用。一个包含一个或多个空格的字符串将返回true。如果您正在使用JQuery,可以简单地使用以下代码:if ($.trim(ref).length === 0),这是类似问题的答案:https://dev59.com/3nI-5IYBdhLWcg3wED9V#6610847。 - CodeClimber
153
正如预期的那样,.length > 0 比与字符串常量进行比较实际上要快得多!请查看此jsPerf链接 - Chad
显示剩余8条评论

1418

为了检查一个变量是否为假值或者它的长度属性是否等于零(对于字符串来说,意味着它是空的),我使用:

function isEmpty(str) {
    return (!str || str.length === 0 );
}

请注意,字符串不是唯一具有length属性的变量,数组也有这个属性,例如。

或者,您可以使用(不太)新的可选链和箭头函数来简化:

const isEmpty = (str) => (!str?.length);

它将检查长度,在空值的情况下返回undefined,而不会抛出错误。在空值的情况下,零是假值,结果仍然有效。

要检查变量是否为假值,或者字符串是否只包含空格或为空,我使用:

function isBlank(str) {
    return (!str || /^\s*$/.test(str));
}

如果你想的话,你可以像这样猴子补丁String原型:

String.prototype.isEmpty = function() {
    // This doesn't work the same way as the isEmpty function used 
    // in the first example, it will return true for strings containing only whitespace
    return (this.length === 0 || !this.trim());
};
console.log("example".isEmpty());

注意,猴子补丁内置类型是有争议的,因为它可能会破坏依赖于现有内置类型结构的代码,无论出于何种原因。

47
为什么要写成0 === str.length而不是str.length === 0? - Vincent
133
条件语句通常会被写成 if (变量 == 常量值) 的形式,如果你忘了一个 '=',那么你就会把常量值赋给变量而不是测试它。尽管代码仍然可以工作,因为你可以在 if 语句中给变量赋值,但更安全的方式是反转常量值和变量的位置。这样当你测试代码时,你会看到一个错误(Invalid lef-hand side in assignment)。你还可以使用类似 JSHint 的工具来禁止在条件中赋值并在你编写这样的代码时得到警告。 - grandouassou
12
“/^\s*$/.test(str)” 可以用 “str.trim().length === 0” 来替换。 - Schadenfreude
51
@Vincent,这也被称为“Yoda 条件”,例如 if blue is the sky。请参见 http://www.dodgycoder.net/2011/11/yoda-conditions-pokemon-exception.html - AZ.
3
尽管可以通过扩展本地原型来实现,但这并不是一个好主意,通常被认为是一种不良实践,很多人强烈建议完全避免这样做,因为有更安全的方式,效果同样好。有一个关于这个话题的SO讨论在这里,但我读过的每一本JS编程书都强烈反对这样做。对于OP的问题,我通常只需执行if (!str) { // 我确定str在这里是空的null或undefined,如果我确定它不是另一种数据类型 } - Stephen M Irving
显示剩余10条评论

554

所有之前的答案都很好,但这个方法会更好。使用双重 NOT 运算符 (!!):

if (!!str) {
    // Some code here
}

或者使用类型转换:

if (Boolean(str)) {
    // Code here
}

两种方法都能实现相同的功能。将变量转换为布尔值,其中 str 是一个变量。

  • 返回值为false的情况有: null, undefined, 0, 000, "", 和 false

  • 返回值为true的情况是除空字符串外的所有字符串值(包括像 "0"" " 这样的字符串)。


57
if(str)if(!!str)的行为有区别吗? - Peter Olson
7
@PeterOlson 如果你想将一个变量保存为布尔类型,来检查多个字符串是否包含内容,那么你需要这样做.. 即 var any = (!!str1 && !!str2 && !!str3) 如果其中还有数字的话,也需要进行处理。 - John Ruddell
51
这是我经常使用的解决方案。 !!str.trim() 确保字符串不仅仅由空格组成。 - Dario Oddenino
29
看起来并不像是黑客攻击,Boolean(str) 更易读且不那么令人困惑。 - shinzou
11
if 语句中,这样做毫无意义,它将假值转换为 false,将真值转换为 trueif 块的执行取决于表达式是否为真值,因此添加 !! 没有任何意义。 - Oli Crt
显示剩余10条评论

133

如果 str 是一个字符串,那么与 str.Empty 最接近的东西是:

if (!str.length) { ...

27
如果str为空,那么这会引发一个异常吗? - Pic Mickael
7
是的!str.Empty也是。 - Ates Goral
请注意,字符串不是唯一具有“length”属性的变量类型。数组也有。 - Flimm

116

如果您需要确保字符串不仅仅是一堆空格(我假设这是用于表单验证),则需要对空格进行替换。

if(str.replace(/\s/g,"") == ""){
}

8
如果您实际上想要测试的是具有非空格内容的字符串,则此方法可行。是否有更便宜的方法来进行此测试? - flash
4
长度属性怎么样? - driAn
30
为什么不只检查是否有非空格字符,而不是删除所有空格?这样有两个好处:一旦出现非空格字符就可以提前退出程序,且无需返回一个新字符串再进行检查。应该使用 if(str.match(/\S/g)) {} - mpen
34
@Mark,FYI,你不需要使用全局修饰符,因为第一个非空格字符的匹配就意味着字符串不是空的:str.match(/\S/) - neezer
2
也许 /\S/.test(str)str.match(/\S/) 更好,因为它不需要返回匹配结果的数组(可能会有微小的性能提升)。此外,当只是针对正则表达式进行测试字符串时,使用 RegExp 的 .test() 方法可以更好地传达意图。 - Ates Goral
显示剩余3条评论

78

我使用:

function empty(e) {
  switch (e) {
    case "":
    case 0:
    case "0":
    case null:
    case false:
    case undefined:
      return true;
    default:
      return false;
  }
}

empty(null) // true
empty(0) // true
empty(7) // false
empty("") // true
empty((function() {
    return ""
})) // false

6
这个解决方案更加不依赖于语言。它只依赖于JavaScript的typeof特性。因此,当你不信任不同浏览器中的实现并且没有时间获取更好的解决方案时(例如无法访问互联网),这是一个可以使用的良好示例。它有点像一个证明。虽然不是最干净的解决方案,但你可以确信它能够正常运行而不需要太多了解JavaScript。 - Jeff Davis
2
我会更进一步,对于未定义的情况使用 === 运算符来确定。否则,这就是完美的答案。 - xarlymg89
1
switch 语句中的 typeof 对我不起作用。我添加了一个 if (typeof e == "undefined") 测试,然后它就能正常工作了。为什么? - Lucas
2
case typeof(e) == "undefined": 是错误的;它匹配的是 falsee,而不是 undefined。显然这是一个被批准的 建议编辑。原始的 case typeof this == "undefined": 仍然没有任何意义。也没有理由认为 false0"0" 是“空”的。 - Sebastian Simon
2
这个函数对于 isEmpty("0") 返回 true,这让我感到惊讶和不希望的行为。在Javascript中,"0" 在布尔上下文中被评估为true,因此我不希望它被认为是空的。 - Flimm
显示剩余5条评论

70

性能

我在macOS v10.13.6(High Sierra)上对18个选择的解决方案进行测试。这些解决方案在某些输入数据的情况下略有不同,如下代码片段所示。

结论

  • !str=====length基础解决方案在所有浏览器(A、B、C、G、I、J)中均较快
  • 基于正则表达式(testreplace)和charAt的解决方案在所有浏览器(H、L、M、P)中最慢
  • 标记为速度最快的解决方案仅在一个测试运行中最快 - 但在许多运行中,它会在“快速”解决方案组内发生变化

Enter image description here

细节

在下面的代码片段中,我通过使用不同的输入参数比较选定的18种方法的结果

  • """a"" " - 空字符串、带有字母的字符串和带有空格的字符串
  • []{}f - 数组、对象和函数
  • 01NaNInfinity - 数字
  • truefalse - 布尔值
  • nullundefined

并非所有测试过的方法都支持所有输入情况。

function A(str) {
  let r=1;
  if (!str)
    r=0;
  return r;
}

function B(str) {
  let r=1;
  if (str == "")
    r=0;
  return r;
}

function C(str) {
  let r=1;
  if (str === "")
    r=0;
  return r;
}

function D(str) {
  let r=1;
  if(!str || 0 === str.length)
    r=0;
  return r;
}

function E(str) {
  let r=1;
  if(!str || /^\s*$/.test(str))
    r=0;
  return r;
}

function F(str) {
  let r=1;
  if(!Boolean(str))
    r=0;
  return r;
}

function G(str) {
  let r=1;
  if(! ((typeof str != 'undefined') && str) )
    r=0;
  return r;
}

function H(str) {
  let r=1;
  if(!/\S/.test(str))
    r=0;
  return r;
}

function I(str) {
  let r=1;
  if (!str.length)
    r=0;
  return r;
}

function J(str) {
  let r=1;
  if(str.length <= 0)
    r=0;
  return r;
}

function K(str) {
  let r=1;
  if(str.length === 0 || !str.trim())
    r=0;
  return r;
}

function L(str) {
  let r=1;
  if ( str.replace(/\s/g,"") == "")
    r=0;
  return r;
}

function M(str) {
  let r=1;
  if((/^\s*$/).test(str))
    r=0;
  return r;
}


function N(str) {
  let r=1;
  if(!str || !str.trim().length)
    r=0;
  return r;
}

function O(str) {
  let r=1;
  if(!str || !str.trim())
    r=0;
  return r;
}

function P(str) {
  let r=1;
  if(!str.charAt(0))
    r=0;
  return r;
}

function Q(str) {
  let r=1;
  if(!str || (str.trim()==''))
    r=0;
  return r;
}

function R(str) {
  let r=1;
  if (typeof str == 'undefined' ||
      !str ||
      str.length === 0 ||
      str === "" ||
      !/[^\s]/.test(str) ||
      /^\s*$/.test(str) ||
      str.replace(/\s/g,"") === "")

    r=0;
  return r;
}




// --- TEST ---

console.log(                  '   ""  "a"  " " [] {} 0 1 NaN Infinity f true false null undefined ');
let log1 = (s,f)=> console.log(`${s}: ${f("")}   ${f("a")}    ${f(" ")}   ${f([])}  ${f({})}  ${f(0)} ${f(1)} ${f(NaN)}   ${f(Infinity)}        ${f(f)} ${f(true)}    ${f(false)}     ${f(null)}    ${f(undefined)}`);
let log2 = (s,f)=> console.log(`${s}: ${f("")}   ${f("a")}    ${f(" ")}   ${f([])}  ${f({})}  ${f(0)} ${f(1)} ${f(NaN)}   ${f(Infinity)}        ${f(f)} ${f(true)}    ${f(false)}`);
let log3 = (s,f)=> console.log(`${s}: ${f("")}   ${f("a")}    ${f(" ")}`);

log1('A', A);
log1('B', B);
log1('C', C);
log1('D', D);
log1('E', E);
log1('F', F);
log1('G', G);
log1('H', H);

log2('I', I);
log2('J', J);

log3('K', K);
log3('L', L);
log3('M', M);
log3('N', N);
log3('O', O);
log3('P', P);
log3('Q', Q);
log3('R', R);

我为所有方法执行速度测试案例str = "",浏览器包括 Chrome v78.0.0、Safari v13.0.4 和 Firefox v71.0.0 - 您可以在您的计算机上运行测试这里

输入图像描述


2
有点误导人,因为它将修剪解决方案与不修剪解决方案混合在一起。 - sean

61

你可以使用lodash:_.isEmpty(value)。

它涵盖了很多情况,比如{}''nullundefined等。

但是它对于JavaScript原始数据类型中的Number类型总是返回true,例如_.isEmpty(10)_.isEmpty(Number.MAX_VALUE)都会返回true


_.isEmpty(" "); // => false - Erich
2
@Erich 因为 " " 不是空的。_.isEmpty(""); 返回 true。 - Moshi
1
非常正确 - 我提到这一点是因为这里的其他答案中有一些暗示了表单验证和检查字符串是否仅由空格组成,而这个单独的lodash函数本身并不能解决这个问题。 - Erich

43

非常通用的“全能”函数(不建议使用):

function is_empty(x)
{
    return (                                                           //don't put newline after return
        (typeof x == 'undefined')
              ||
        (x == null)
              ||
        (x == false)        //same as: !x
              ||
        (x.length == 0)
              ||
        (x == 0)            // note this line, you might not need this. 
              ||
        (x == "")
              ||
        (x.replace(/\s/g,"") == "")
              ||
        (!/[^\s]/.test(x))
              ||
        (/^\s*$/.test(x))
    );
}

不过,我不建议使用这种方法,因为你的目标变量应该是特定类型的(例如字符串、数字或对象),所以应该应用与该变量相关的检查。


3
可以请问您能否说明每个检查项的作用呢? :) - DanV
4
他们正在测试不同的东西,将它们全部放在一个if语句中没有意义。 - Bennett McElwee
2
typeof MyVariable == 'undefined' 无法区分已初始化但值为 undefined 的变量和未声明的变量,除非该变量最初被声明并初始化为 null。检查 length 属性会导致字符串原始值被包装在字符串对象中。 - Scott Marcus

42
var s; // undefined
var s = ""; // ""
s.length // 0

在JavaScript中,没有用于表示空字符串的任何内容。如果您知道变量将始终是字符串,请使用length进行检查,否则请使用""进行检查。


我不理解这句话的意思:“在JavaScript中没有代表空字符串的东西。”。那么 "" 不是代表空字符串吗? - Flimm

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