JavaScript 检查变量是否存在(已定义 / 初始化)

哪种方法检查变量是否已初始化是更好 / 正确的方法? (假设变量可以容纳任何内容(字符串,整数,对象,函数等)。

if (elem) { // or !elem

要么

if (typeof(elem) !== 'undefined') {

要么

if (elem != null) {

答案

您需要typeof运算符 。特别:

if (typeof variable !== 'undefined') {
    // the variable is defined
}

typeof运算符将检查变量是否确实未定义。

if (typeof variable === 'undefined') {
    // variable is undefined
}

与其他运算符不同, typeof运算符与未声明的变量一起使用时不会引发ReferenceError异常。

但是,请注意typeof null将返回"object" 。我们必须小心避免将变量初始化为null的错误。为了安全起见,我们可以改用以下方法:

if (typeof variable === 'undefined' || variable === null) {
    // variable is undefined or null
}

有关使用严格比较===而不是简单等式==更多信息,请参见:
JavaScript 比较中应使用哪个等于运算符(== vs ===)?

在 JavaScript 中,可以定义一个变量,但是将其值保留为undefined ,因此最常见的答案在技术上并不正确,而是执行以下操作:

if (typeof v === "undefined") {
   // no variable "v" is defined in the current scope
   // *or* some variable v exists and has been assigned the value undefined
} else {
   // some variable (global or local) "v" is defined in the current scope
   // *and* it contains a value other than undefined
}

这可能足以满足您的目的。以下测试具有更简单的语义,这使得更容易精确地描述代码的行为并亲自理解(如果您关心这样的事情):

if ("v" in window) {
   // global variable v is defined
} else {
   // global variable v is not defined
}

当然,这假定您正在浏览器中运行(其中window是全局对象的名称)。但是,如果您想像这样的全局变量,则可能是在浏览器中。从主观上讲, 'name' in window使用'name' in window样式上与使用window.name引用全局变量一致。作为window属性而不是变量访问全局变量,可以使您在代码中引用的未声明变量的数量最少(以利于衬里),并避免全局变量被局部变量覆盖的可能性。另外,如果全局对象使您的皮肤爬行,则仅用此相对较长的棍子接触它们时,您可能会感到更舒适。

在许多情况下,使用:

if (elem) { // or !elem

将为您完成工作!... 这将检查以下情况:

  1. 未定义 :如果没有定义的值,它的undefined
  2. null :如果为 null,例如,如果 DOM 元素不存在...
  3. 空字符串''
  4. 0 :数字零
  5. NaN :不是数字

因此,它将涵盖所有情况,但总有一些奇怪的情况我们也想涵盖,例如,一个带有空格的字符串,例如' ' ,将在 javascript 中定义,因为它具有空格内部字符串... 例如,在这种情况下,您可以使用 trim()添加另一项检查,例如:

if(elem) {

if(typeof elem === 'string' && elem.trim()) {
///

另外,这些检查仅针对 ,因为对象和数组在 Javascript 中的工作方式不同,因此空 array []和空 object {}始终为true

我创建下面的图像以快速显示答案:

未定义,null等

在大多数情况下,您将使用:

elem != null

与简单的if (elem) ,它允许0falseNaN'' ,但拒绝nullundefined ,这使其成为对是否存在参数或对象属性的良好常规测试。


其他检查也不是不正确,只是用途不同:

  • if (elem) :如果保证elem是一个对象,或者将false0等视为 “默认” 值(因此等效于undefinednull ),则可以使用。

  • 如果指定的null对未初始化的变量或属性具有独特的含义,则可以使用typeof elem == 'undefined'

    • 如果未声明 elem (即,没有var语句,不是window的属性或不是函数参数), 这是不会引发错误的唯一检查。在我看来,这是相当危险的,因为它会使错别字误入歧途。为避免这种情况,请参见以下方法。

undefined进行严格比较也很有用:

if (elem === undefined) ...

但是,由于全局undefined可以用另一个值覆盖,因此最好在使用前在当前作用域中声明该变量undefined

var undefined; // really undefined
if (elem === undefined) ...

要么:

(function (undefined) {
    if (elem === undefined) ...
})();

该方法的第二个优点是,JS 缩小器可以将undefined变量减少为单个字符,每次可以节省几个字节。

如何检查变量是否存在

这是一个相当不错的解决方案,用于测试变量是否存在并已初始化:

var setOrNot = typeof variable !== typeof undefined;

它最常与三元运算符结合使用以在未初始化某些变量的情况下设置默认值:

var dark = typeof darkColor !== typeof undefined ? darkColor : "black";

封装问题

不幸的是,您不能简单地将检查封装在函数中。

您可能会想到做这样的事情:

function isset(variable) {
    return typeof variable !== typeof undefined;
}

但是,如果您调用例如,这将产生参考错误。 isset(foo)和变量foo尚未定义,因为您不能将不存在的变量传递给函数:

未捕获的 ReferenceError:未定义 foo


测试功能参数是否未定义

虽然我们的isset函数不能用于测试变量是否存在(出于上述原因),但它确实允许我们测试函数的参数是否未定义:

var a = '5';

var test = function(x, y) {
    console.log(isset(x));
    console.log(isset(y));
};

test(a);

// OUTPUT :
// ------------
// TRUE
// FALSE

即使没有将y值传递给函数test ,我们的isset函数在这种情况下也可以完美运行,因为y在函数test被称为undefined值。

检查是否有windowhasOwnPropertyvarname

到的大量的替代typeof答案;

var varname = value;声明的全局变量var varname = value;全球范围内的声明

可以作为窗口对象的属性进行访问。

因此, hasOwnProperty()方法

返回一个布尔值,指示对象是否具有指定的属性作为其自己的属性(而不是继承它)

可以用来确定是否

“varname”var已被全局声明, window的属性。

// Globally established, therefore, properties of window
var foo = "whatever", // string
    bar = false,      // bool
    baz;              // undefined
//  window.qux does not exist

console.log( [
    window.hasOwnProperty( "foo" ), // true
    window.hasOwnProperty( "bar" ), // true
    window.hasOwnProperty( "baz" ), // true
    window.hasOwnProperty( "qux" )  // false
] );

hasOwnProperty()在于,在调用它时,我们没有使用可能尚未声明的变量 - 当然,这首先是问题的一半。

尽管并非总是 完美理想的解决方案,但在某些情况下,这只是工作!

笔记

与使用 let相比, 使用var定义变量时上述情况是正确的

声明一个块范围局部变量,可以选择将其初始化为一个值。

var关键字不同,该关键字在全局范围内或整个函数本地定义变量,而与块范围无关。

在程序和函数的顶层, letvar不同,不会在全局对象上创建属性。

为了完整 const const常量根据定义实际上不是变量(尽管它们的内容可以);更相关地:

var变量不同,全局常量不会成为 window 对象的属性。需要一个常量的初始化程序;也就是说,您必须在声明它的同一条语句中指定它的值。

常量的值不能通过重新分配而更改,也不能重新声明。

const 声明创建对值的只读引用。这并不意味着它拥有的值是不可变的,只是不能重新分配变量标识符。

由于let变量或const常量绝不是继承了hasOwnProperty()方法的任何对象的属性,因此无法将其用于检查它们的存在。

关于hasOwnProperty()的可用性和使用:

Object派生的每个对象都继承hasOwnProperty()方法。与in运算符不同,此方法不会检查对象的原型链。

当您执行简单的分配和相关检查时,还有另一种简便的方法可以进行检查。只需使用条件(三元)运算符。

var values = typeof variable !== 'undefined' ? variable : '';

当您尝试使用引用变量的实例分配声明全局变量时,这也将有所帮助。

如果要检查变量,则不能为undefinednull 。然后执行以下检查。

声明变量后,如果要检查值,这甚至很简单: 它将一起执行undefinednull检查。

var values = variable ? variable : '';

这取决于您是否只是关心已定义变量,还是希望它具有有意义的值。

检查类型是否未定义将检查变量是否已定义。

=== null!== null仅检查变量的值是否恰好为null

== null!= null将检查该值是undefined还是null

if(value)将检查变量是否为undefinednull0或空字符串。

未声明(未定义)测试变量的简短方法是

if (typeof variable === "undefined") {
  ...
}

我发现它对于检测在浏览器外部运行的脚本(没有声明window变量)很有用。