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

JavaScript check if variable exists (is defined/initialized)

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

1
if (elem) { // or !elem

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

1
if (elem != null) {


您需要typeof运算符。明确地:

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


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

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

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

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

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

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


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

1
2
3
4
5
6
7
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
}

这就够了。下面的测试具有更简单的语义,这使得准确描述代码的行为和自己理解代码变得更容易(如果您关心这些事情):

1
2
3
4
5
if ("v" in window) {
   // global variable v is defined
} else {
   // global variable v is not defined
}

当然,这假定您在浏览器中运行(其中window是全局对象的名称)。但是,如果你和这样的全球公司混在一起,你可能在一个浏览器里。主观上,使用'name' in window在风格上与使用window.name表示全局一致。访问globals作为window的属性,而不是作为变量,可以使您在代码中引用的未声明变量的数量最小化(有利于linting),并避免全局被局部变量隐藏的可能性。此外,如果全球变暖让你的皮肤爬行,你可能会觉得只有用这个相对较长的棍子触摸它们更舒服。


在许多情况下,使用:

1
if (elem) { // or !elem

会为你做的!…这将检查以下情况:

  • 未定义:如果该值未定义且为undefined
  • 空:例如,如果它是空的,如果一个dom元素不存在…
  • 空字符串:''
  • 0:零号
  • 南:不是数字
  • 所以它将覆盖所有的情况,但我们总是想覆盖一些奇怪的情况,例如,一个带有空格的字符串,像这个' '1,它将在javascript中定义,因为它在字符串中有空格…例如,在这种情况下,您可以使用trim()再添加一个检查,例如:

    1
    2
    3
    4
    if(elem) {

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

    此外,这些检查仅用于值,因为对象和数组在JavaScript中的工作方式不同,空数组[]和空对象{}始终为真。

    我创建了下面的图片,以显示答案的简短信息:

    undefined, null, etc


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

    1
    elem != null

    与简单的if (elem)不同,它允许0falseNaN'',但拒绝nullundefined,使其成为一个很好的、通用的关于存在一个论据或一个物体属性的测试。

    其他检查也不正确,它们只是有不同的用途:

    • if (elem):如果保证elem是一个对象,或者如果false0等被认为是"默认"值(因此相当于undefinednull时,可以使用。

    • 当指定的null对未初始化的变量或属性具有不同的含义时,可以使用typeof elem == 'undefined'

      • 如果没有声明elem语句(即没有var语句,不是window的属性,或者不是函数参数),这是唯一不会引发错误的检查。在我看来,这是相当危险的,因为它会让打字错误被忽视。要避免这种情况,请参见下面的方法。

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

    1
    if (elem === undefined) ...

    但是,由于全局undefined可以被另一个值覆盖,因此在使用变量undefined之前,最好在当前范围内声明它:

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

    或:

    1
    2
    3
    (function (undefined) {
        if (elem === undefined) ...
    })();

    这种方法的第二个优点是JS微型处理器可以将undefined变量减少到单个字符,每次节省几个字节。


    如何检查变量是否存在

    如果变量存在并已初始化,则这是一个非常可靠的测试解决方案:

    1
    var setOrNot = typeof variable !== typeof undefined;

    通常与三元运算符结合使用,以在某个变量未初始化时设置默认值:

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

    封装问题

    不幸的是,您不能简单地封装您的签入函数。

    你可能会想这样做:

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

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

    Uncaught ReferenceError: foo is not defined

    测试功能参数是否未定义

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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值。


    检查对象是否为hasOwnProperty()

    除了过多的typeof答案之外,还有一种选择,就是使用hasOwnProperty(),它当然会检查对象(几乎所有JS中的东西)是否具有属性,即变量(除其他之外)。

    The hasOwnProperty() method returns a boolean indicating whether the object has the specified property as own (not inherited) property.

    Every object descended from Object inherits the hasOwnProperty() method. This method can be used to determine whether an object has the specified property as a direct property of that object; unlike the in operator, this method does not check down the object's prototype chain.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 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
        { foo: [], bar: 0 }.hasOwnProperty("bar" ) // true
    ] );

    hasOwnProperty()的优点在于,在调用它时,我们不使用可能尚未定义的变量——当然,这是问题的一半。

    虽然并不总是完美或理想的解决方案,但在某些情况下,这只是工作!


    当您执行简单的任务和相关的检查时,还有另一种简短的检查方法。只需使用条件(三元)运算符。

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

    当您试图用引用变量的实例赋值来声明全局变量时,这也是很有帮助的。

    如果要检查变量,则不应是undefinednull。然后执行下面的检查。

    当声明变量时,如果您想检查该值,这就更简单了:它将同时执行undefinednull检查。

    1
    var values = variable ? variable : '';


    这取决于您是否关心变量是否已经定义,或者您是否希望它有一个有意义的值。

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

    === null!== null只检查变量的值是否正好是null

    == null!= null将检查值是否为undefinednull

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


    未定义,布尔值,字符串,数字,函数

    1
    2
    3
    if( typeof foo !== 'undefined' ) {

    }

    数组对象

    1
    2
    3
    if( foo instanceof Array ) {

    }


    最高的答案是正确的,使用typeof。

    然而,我想指出的是,在javascript中,undefined是可变的(出于某种不道德的原因)。因此,仅仅检查varName !== undefined就有可能不会像您预期的那样总是返回,因为其他lib可能已经更改为未定义。一些答案(例如@skalee's)似乎不喜欢使用typeof,这可能会给你带来麻烦。

    处理这种情况的"老"方法是将未定义的变量声明为var,以抵消undefined的任何潜在的减乘/过乘。然而,最好的方法仍然是使用typeof,因为它将忽略对其他代码的undefined的任何覆盖。尤其是如果你正在编写代码供在野外使用,谁知道还有什么可以在页面上运行…


    1
    2
    3
    if (typeof console !="undefined") {    
       ...
    }

    或更好

    1
    2
    3
    if ((typeof console =="object") && (typeof console.profile =="function")) {    
       console.profile(f.constructor);    
    }

    适用于所有浏览器


    为了引起争论,如果我知道变量应该是一个字符串或一个对象,我总是喜欢if (!variable),所以检查它是否有问题。这样可以使代码更干净,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    if (typeof data !=="undefined" && typeof data.url ==="undefined") {
        var message = 'Error receiving response';
        if (typeof data.error !=="undefined") {
            message = data.error;
        } else if (typeof data.message !=="undefined") {
            message = data.message;
        }
        alert(message);
    }

    …可以简化为:

    1
    2
    3
    4
    if (data && !data.url) {
      var message = data.error || data.message || 'Error receiving response';
      alert(message)
    }


    空是javascript中的一个值,typeof null返回"object"

    因此,如果传递空值,接受的答案将不起作用。如果传递空值,则需要额外检查空值:

    1
    2
    3
    4
    if ((typeof variable !=="undefined") && (variable !== null))  
    {
       // the variable is defined and not null
    }


    很难区分未定义和空值。空是一个值,当您希望指示变量没有特定值时,可以将该值赋给变量。未定义是一个特殊值,它将是未分配变量的默认值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <wyn>
    var _undefined;
    var _null = null;

    alert(_undefined);
    alert(_null);
    alert(_undefined == _null);
    alert(_undefined === _null);
    </wyn>


    这些答案(除了FredGandt的解决方案)要么不正确要么不完整。

    假设我需要我的variableName;携带一个undefined值,因此它是以var variableName;这样的方式声明的,这意味着它已经初始化了;—我如何检查它是否已经声明了?

    或者更好——我该如何立即检查"book1.chapter22.paragraph37"是否存在一个单独的调用,但不会引起引用错误?

    我们通过使用最强大的jasvascript运算符,即in运算符来实现它。

    1
    2
    "[variable||property]" in [context||root]
    >> true||false

    在Ajax普及率达到顶峰的时候,我编写了一个方法(后来命名为)isns(),它能够确定命名空间是否存在,包括对"book1.chapter22.paragraph37"等属性名的深度测试。

    但是,由于它以前已经发布过,而且由于它的重要性,它应该在一个单独的线程中发布,因此我不会在这里发布它,而是提供关键字(javascript+isns),帮助您定位源代码,并提供所有必要的解释。


    最坚固的"是它定义的"检查是用typeof

    1
    if (typeof elem === 'undefined')

    如果您只是检查一个定义的变量来分配一个默认值,对于一个易于读取的一行程序你可以经常这样做:

    1
    elem = elem || defaultElem;

    通常可以使用,请参见:在javascript中设置默认值的惯用方法

    还有一个使用typeof关键字的行程序:

    1
    elem = (typeof elem === 'undefined') ? defaultElem : elem;

    您可以使用typeof操作符。

    例如,

    1
    2
    3
    var dataSet;

    alert("Variable dataSet is :" + typeof dataSet);

    上面的代码段将返回类似

    variable dataSet is : undefined.


    在问题中概述的特定情况下,

    1
    typeof window.console ==="undefined"

    相同

    1
    window.console === undefined

    我比较喜欢后者,因为它比较短。

    请注意,我们只在全局范围内查找console(这是所有浏览器中的window对象)。在这种特殊情况下,这是可取的。我们不希望在其他地方定义console

    @Briankelley在他的伟大回答中解释了技术细节。我只是添加了一些缺乏结论的内容,并将其消化为更容易阅读的内容。


    如果要定义的块执行某些操作,请使用

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

    如果希望未定义的块执行某些操作或分配或定义变量,请使用

    1
    2
    3
    if (typeof variable === 'undefined') {
        // the variable is undefined
    }

    我的首选是typeof(elem) != 'undefined' && elem != null

    不管您如何选择,请考虑将检查放入类似这样的函数中

    1
    2
    3
    function existy (x) {
        return typeof (x) != 'undefined' && x != null;
    }

    如果不知道声明了变量,则继续执行typeof (x) != 'undefined' && x != null;

    如果知道变量已声明但可能不存在,则可以使用

    1
    existy(elem) && doSomething(elem);

    您正在检查的变量有时可能是嵌套属性。您可以使用prop向下检查存在问题的属性:

    1
    var exists = ((((existy(myObj).prop1||{}).prop2||{}).prop3||{})[1]||{}).prop4;

    在每个属性之后使用(…'')。

    或者你可以使用existy,比如existy(o) && existy(o.p) && existy(o.p.q) && doSomething(o.p.q)


    根据对象的不同,我使用两种不同的方法。

    1
    2
    3
    4
    5
    6
    7
    8
    if( !variable ){
      // variable is either
      // 1. '';
      // 2. 0;
      // 3. undefined;
      // 4. null;
      // 5. false;
    }

    有时我不想将空字符串评估为假字符串,所以我使用这个案例

    1
    2
    3
    4
    5
    6
    7
    function invalid( item ){
      return (item === undefined || item === null);
    }

    if( invalid( variable )){
      // only here if null or undefined;
    }

    如果你需要相反的东西,那么首先!变量变为!!variable,且在无效函数中===变为!=函数名变为NotInvalid。


    功能更强大,使用更方便:

    1
    2
    3
    4
    function exist(obj)
    {
        return (typeof obj !== 'undefined');
    }

    函数将返回true(如果存在),否则返回false(如果不存在)。


    这取决于情况。如果您正在检查可能或可能没有在代码外部全局定义的内容(例如jquery),您需要:

    1
    if (typeof(jQuery) !="undefined")

    (这里不需要严格相等,typeof总是返回一个字符串。)但是,如果您有一个函数的参数可能已经传递过,也可能没有传递过,那么它们将始终被定义,如果省略,则为空。

    1
    2
    3
    4
    5
    function sayHello(name) {
        if (name) return"Hello," + name;
        else return"Hello unknown person";
    }
    sayHello(); // =>"Hello unknown person"


    简单点怎么样:

    1
    2
    3
    if(!!variable){
      //the variable is defined
    }


    我很惊讶这还没被提到…

    下面是一些使用this['var_name']的附加变体

    1
    2
    3
    4
    5
    6
    if (this['elem']) {...}; // less safe than the res but works as long as you're note expecting a falsy value
    if (this['elem'] !== undefined) {...}; // check if it's been declared
    if (this['elem'] !== undefined && elem !== null) {...}; // check if it's not null, you can use just elem for the second part

    // these will work even if you have an improper variable definition declared here
    elem = null; // <-- no var here!! BAD!

    请注意,当您检查时!=或!=对"未定义"无效

    在Firfox Quantom 60.0.1上测试

    使用这样的测试来避免冲突

    1
    2
    3
    4
    5
    6
    7
    8
    9
    if(!(typeof varibl['fl'] === 'undefined')) {

                console.log(varibl['fl']);
                console.log("Variable is Defined");
            }else{

                console.log(varibl['fl']);
                console.log("Variable is Un-Defined");
            }


    为了检查变量是否已经声明/设置,我做了这个肮脏的技巧。

    我还没有找到将代码提取到函数的方法,即使使用eval

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    "use strict";

    // var someVar;

    var declared;
    try {
      someVar;
      declared = true;
    } catch(e) {
      declared = false;
    }

    if (declared) {
      console.log("someVar is declared; now has the value:" + someVar);
    } else {
      console.log("someVar is not declared");
    }

    我在上面的答案中看不到这个,所以我想我会在这里提出建议。

    1
    2
    3
    4
    5
    function isDefined(x) { return !!x }

    if( isDefined(x) ) {
        //The variable is defined
    }

    !x将返回真正的iff x为空或未定义,所以!!x将只返回true iff x既不是未定义也不是空值。

    我知道这也解释了无效案例,但这里有一个公平的警告。