ChatGPT解决这个技术问题 Extra ChatGPT

如何检查 JavaScript 中的“未定义”? [复制]

这个问题在这里已经有了答案:Detecting an undefined object property (50 answers) How to check a not-defined variable in JavaScript (15 answers) How to handle 'undefined' in JavaScript [duplicate] (3 answers) How can I check if JavaScript 中是否存在变量? (8 个回答) 7 年前关闭。

测试 JavaScript 中是否未定义变量的最合适方法是什么?

我见过几种可能的方法:

if (window.myVariable)

或者

if (typeof(myVariable) != "undefined")

或者

if (myVariable) // This throws an error if undefined. Should this be in Try/Catch?
您要检查only undefined,还是同时检查null
@Robert - 这个问题有一个公认的答案,这里的答案已被证明是错误的
那个“重复”是关于对象属性的,所以一些答案不太适用于这个问题,询问变量。

r
reformed

如果您有兴趣了解变量是否已被声明而不管其值如何,那么使用 in 运算符是最安全的方法。考虑这个例子:

// global scope
var theFu; // theFu has been declared, but its value is undefined
typeof theFu; // "undefined"

但这在某些情况下可能不是预期的结果,因为变量或属性已声明但未初始化。使用 in 运算符进行更可靠的检查。

"theFu" in window; // true
"theFoo" in window; // false

如果您想知道变量是否尚未声明或是否具有值 undefined,请使用 typeof 运算符,它保证返回一个字符串:

if (typeof myVar !== 'undefined')

undefined 的直接比较很麻烦,因为 undefined 可能会被覆盖。

window.undefined = "foo";
"foo" == undefined // true

正如@CMS 所指出的,这已在 ECMAScript 第 5 版中进行了修补,并且 undefined 是不可写的。

if (window.myVar) 还将包含这些虚假值,因此它不是很可靠:

false
0
""
NaN
null
undefined

感谢@CMS 指出您的第三种情况 - if (myVariable) 在两种情况下也可能引发错误。第一种是未定义变量时抛出 ReferenceError

// abc was never declared.
if (abc) {
    // ReferenceError: abc is not defined
} 

另一种情况是变量已定义,但有一个 getter 函数,该函数在调用时会引发错误。例如,

// or it's a property that can throw an error
Object.defineProperty(window, "myVariable", { 
    get: function() { throw new Error("W00t?"); }, 
    set: undefined 
});
if (myVariable) {
    // Error: W00t?
}

@Anurag,如果 myVariable声明,第三种情况将抛出 ReferenceError ...
@Anurag,不客气,因为您谈到了 ES5,也许值得一提的是 undefined 现在被描述为不可写、不可配置和不可枚举。因此,window.undefined = "omg"; 将简单地以静默方式失败或在严格模式下抛出。
可以重新定义“typeof”吗?
typeof 是一种语言语句,它不能被重新定义,就像 if/else/while/for/function 等一样。
undefined现代浏览器中是不可变的。设置 window.undefined 什么都不做。
T
Thomas Eding

我个人使用

myVar === undefined

警告:请注意 === 用于 == 并且 myVar 之前已声明(未定义)。

我不喜欢typeof myVar === "undefined"。我认为这是冗长而不必要的。 (我可以用更少的代码完成同样的工作。)

现在有些人读到这里会痛得头晕目眩,尖叫:“等等!WAAITTT!!!undefined可以重新定义!”

凉爽的。我知道这个。再说一遍,Javascript 中的大多数变量都可以重新定义。你不应该使用任何可以重新定义的内置标识符吗?

如果你遵循这条规则,对你有好处:你不是伪君子。

问题是,为了在 JS 中做大量实际工作,开发人员需要依赖可重新定义的标识符才能成为他们的样子。我没有听到有人告诉我不应该使用 setTimeout,因为有人可以

window.setTimeout = function () {
    alert("Got you now!");
};

最重要的是,不使用原始 === undefined 的“它可以重新定义”的论点是虚假的。

(如果您仍然害怕重新定义 undefined,为什么要盲目地将未经测试的库代码集成到您的代码库中?或者更简单:一个 linting 工具。)

此外,与 typeof 方法一样,此技术可以“检测”未声明的变量:

if (window.someVar === undefined) {
    doSomething();
}

但是这两种技术都在抽象中泄漏。我敦促你不要使用这个,甚至

if (typeof myVar !== "undefined") {
    doSomething();
}

考虑:

var iAmUndefined;

要了解该变量是否已声明,您可能需要使用 in 运算符。 (在许多情况下,您可以简单地阅读代码 O_o)。

if ("myVar" in window) {
    doSomething();
}

可是等等!还有更多!如果发生了一些原型链魔法怎么办……?现在,即使是高级 in 运算符也不够用。 (好吧,这部分我已经讲完了,只是说在 99% 的时间里,=== undefined(和 ****cough**** typeof)工作得很好。如果你真的在乎,你可以自己阅读有关此主题的内容。)


重新定义 undefined 的可能性稍大一些,因为人们确实将它用于此类检查。有些人在进行此类检查时习惯性地将常数放在左侧:if (undefined == someVariable)。只需一个错字就可以静默地重新定义 undefinedif (undefined = someVariable)
我从不在 LHS 上编写具有 undefined 的代码。即使我这样做了,我使用 === 而不是 == 的事实也使得错字极不可能出现。但 == 不正确的事实更令人担忧。无论如何,这样的错误通常很容易找到。有点像这个错误:typeof x == "undefned"
这怎么可能被投票 41 次,它根本行不通。如果 myVar 确实未定义,则代码将抛出错误,并且很容易测试 - jsfiddle.net/WcM5g 正确的方法是 typeof myVar === 'undefined'
@Laurent:开个玩笑吧?这假定变量是以某种方式声明的,例如通过 var 关键字或函数参数。在我(故意)编写尝试以任何方式对未声明的变量进行操作的代码之前,我会出卖自己的灵魂。请记住,未声明和未定义是 JS 中的两个不同概念。
@Andy在C(和C ++)中,像这样反转操作数以避免拼写错误是常见且良好的做法。 if (NULL = myVar) 无法编译并立即被捕获,而 if (myVar = NULL) 会产生一个可能难以追踪的错误,具体取决于它周围的其他代码。现代编译器应该给你一个警告,但是许多有经验的 C 程序员已经养成了交换顺序的习惯。
T
Tim Down

2020 更新

我更喜欢 typeof 检查(即 undefined 可以重新定义)的原因之一与 ECMAScript 5 的大规模采用无关。另一个,您可以使用 typeof 检查未声明变量的类型,总是小众。因此,我现在建议在大多数情况下使用直接比较:

myVariable === undefined

2010年的原始答案

使用 typeof 是我的偏好。当变量从未被声明时,它将起作用,这与与 ===== 运算符的任何比较或使用 if 的类型强制不同。 (与 null 不同,undefined 也可能在 ECMAScript 3 环境中重新定义,这使得比较不可靠,尽管现在几乎所有常见的环境都与 ECMAScript 5 或更高版本兼容)。

if (typeof someUndeclaredVariable == "undefined") {
    // Works
}

if (someUndeclaredVariable === undefined) { 
    // Throws an error
}

您可能想要检查是否已经定义了代表某项功能的特定全局变量。例如,库代码可能希望检查该库以前是否未被包含。
窗口中的“xyz”或自我中的“xyz”要好得多
@JamiePate:为了清楚起见,我不同意 'xyz' in window 是比 typeof xyz == "undefined" 更好的答案,因为它正在测试错误的东西。 in 运算符检查属性是否存在,而不管其值如何,而问题至少似乎是在询问如何测试变量的值是否为 undefinedvar foo; "foo" in window 可能是我选择的一个更好的例子;这返回 true 而 foo 肯定是未定义的。
@JamiePate:为什么 xyz === undefinedtypeof xyz == "undefined" 好?同意全局变量,但我们两个中只有您一直建议检查 window 的属性。
在大多数情况下它是多余的(并且可读性较差)。如果你知道 xyz 是一个声明的变量,为什么还要经历额外的麻烦呢?在某些浏览器中类型检查和字符串比较要慢得多,所以如果你在一个紧密的循环中做很多事情,你会失去一些性能。 jsperf.com/type-of-undefined-vs-undefined/6
J
Jacob Relkin

您可以使用 typeof,如下所示:

if (typeof something != "undefined") {
    // ...
}

或者只是 something !== undefined,假设您已经谨慎地完成了 var undefined
很高兴看到您现在添加了引号。但是,如 my answer 中所述,请注意在这种情况下不需要严格比较 (!==),因为 typeof 将始终返回一个字符串。
Mathias:这里使用严格或非严格比较是个人喜好问题。两者都将始终有效,而且都不是更正确的。这可能取决于您的默认位置是始终使用严格比较,除非特别需要类型强制(例如 Crockford 推荐的),或者您是否更喜欢使用非严格比较,除非需要严格性。
这是不准确的。您绝对没有需要使用 typeof
哦,现在我明白你的意思了;您的评论具有误导性,因为看起来与代码的正确性有关。是的,一个人不需要使用它,因为一切都取决于品味; 如果你知道自己在做什么,你甚至不需要清理用户输入;这并不意味着它不应该完成。在这种情况下,在所有答案中,使用 typeof 是最安全且不易出错的选项。除了写这样令人困惑的评论之外,我还会编辑答案以使用另一个术语而不是 need。比如 “你可以|应该|更好|可能使用 typeof :)
K
Kamafeather

2018-07-25 更新

这篇文章第一次发表已经将近五年了,JavaScript 已经走过了漫长的道路。在重复原始帖子中的测试时,我发现以下测试方法之间没有一致的区别:

abc === 未定义

abc === 无效 0

typeof abc == '未定义'

typeof abc === '未定义'

即使我修改了测试以防止 Chrome 优化它们,但差异并不显着。因此,为了清楚起见,我现在推荐 abc === undefined

chrome://version 的相关内容:

Google Chrome:67.0.3396.99(官方版本)(64 位)(同类群组:稳定)

修订:a337fbf3c2ab8ebc6b64b0bfdce73a20e2e2252b-refs/branch-heads/3396@{#790}

操作系统:Windows

JavaScript:V8 6.7.288.46

用户代理:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36

原帖 2013-11-01

在 Google Chrome 中,以下测试比 typeof 测试要快一点:

if (abc === void 0) {
    // Undefined
}

差异可以忽略不计。但是,对于知道 void 0 含义的人来说,这段代码更加简洁明了。但请注意,abc 仍必须声明

typeofvoid 都明显快于直接与 undefined 比较。我在 Chrome 开发者控制台中使用了以下测试格式:

var abc;
start = +new Date();
for (var i = 0; i < 10000000; i++) {
    if (TEST) {
        void 1;
    }
}
end = +new Date();
end - start;

结果如下:

Test: | abc === undefined      abc === void 0      typeof abc == 'undefined'
------+---------------------------------------------------------------------
x10M  |     13678 ms               9854 ms                 9888 ms
  x1  |    1367.8 ns              985.4 ns                988.8 ns

请注意,第一行以毫秒为单位,而第二行以纳秒为单位。 3.4 纳秒的差异不算什么。在随后的测试中,时间非常一致。


哇,太令人心碎了,这是-1;我花了很多时间来测试这个。那好吧。这是很好的信息,所以我会把它留在这里。请记住,不要使用 === 来测试 undefined
我认为 -1 是因为 1) <q>对于知道 void 0 意味着什么的人来说一目了然</q>,因为 void 0 对我来说听起来更不寻常,2) 你应该改为 share your perf tests ,但主要是 3) 如果 abc 未定义,您的第一个示例 (abc === void 0) 将引发异常。
将您的方法添加到我的测试列表中,并且确实可以检查(不是我怀疑您)- jsfiddle.net/drzaus/UVjM4/8
鉴于这些数字(来自不久前的数据),我认为在清晰度和速度之间的最佳折衷方案是 typeof 测试。
我发现 undefined 比较比 void 0 慢,这很令人惊讶。我想运行的 JS 版本足够新,可以保证 undefined 保持不变。好难过。
G
Guffa

如果它是未定义的,它将不等于包含字符“未定义”的字符串,因为该字符串不是未定义的。

您可以检查变量的类型:

if (typeof(something) != "undefined") ...

有时您甚至不必检查类型。如果变量的值在设置时不能评估为 false(例如,如果它是一个函数),那么您可以只评估变量。例子:

if (something) {
  something(param);
}

不需要括号:typeof 是运算符,而不是函数。
@Tim - 它可以两种方式使用。
@Tim:@Nick 是正确的。请参阅developer.mozilla.org/en/Core_Javascript_1.5_Reference/…
是的,我知道它可以与括号一起使用,这是因为这里的括号形成了分组运算符,它简单地计算并返回内部的操作数。我只是说它们是不必要的。
M
Mathias Bynens
if (typeof foo == 'undefined') {
 // Do something
};

请注意,在这种情况下不需要严格比较 (!==),因为 typeof 将始终返回一个字符串。


分号 (};) 是什么?
@JP:右大括号后的分号只是一个空语句。
@Gumbo,对不起,我的意思是:“分号的用途是什么?”
我没有遇到过没有 ; 就无法处理 if(){} 的缩小器……您指的是哪些缩小器?你说这就是你结束所有其他陈述的方式......我想这是真的。但是,块语句 {} 已经是它自己的语句。从技术上讲,添加 ; 使其成为两个语句。从语法上讲,它是多余的。即使是自动分号插入也不会在那里添加分号......
@JP:我想我几年前在阅读 the Packer documentation 后就开始这样做了。 Packer 需要在 function() {} 声明之后使用分号。你是对的——显然在 if 语句之后不需要它,但不知何故我仍然认为它是有道理的。
d
drzaus

说明各种答案结果的一些场景:http://jsfiddle.net/drzaus/UVjM4/

(请注意,在作用域包装器中使用 var 进行 in 测试会有所不同)

参考代码:

(function(undefined) {
    var definedButNotInitialized;
    definedAndInitialized = 3;
    someObject = {
        firstProp: "1"
        , secondProp: false
        // , undefinedProp not defined
    }
    // var notDefined;

    var tests = [
        'definedButNotInitialized in window',
        'definedAndInitialized in window',
        'someObject.firstProp in window',
        'someObject.secondProp in window',
        'someObject.undefinedProp in window',
        'notDefined in window',

        '"definedButNotInitialized" in window',
        '"definedAndInitialized" in window',
        '"someObject.firstProp" in window',
        '"someObject.secondProp" in window',
        '"someObject.undefinedProp" in window',
        '"notDefined" in window',

        'typeof definedButNotInitialized == "undefined"',
        'typeof definedButNotInitialized === typeof undefined',
        'definedButNotInitialized === undefined',
        '! definedButNotInitialized',
        '!! definedButNotInitialized',

        'typeof definedAndInitialized == "undefined"',
        'typeof definedAndInitialized === typeof undefined',
        'definedAndInitialized === undefined',
        '! definedAndInitialized',
        '!! definedAndInitialized',

        'typeof someObject.firstProp == "undefined"',
        'typeof someObject.firstProp === typeof undefined',
        'someObject.firstProp === undefined',
        '! someObject.firstProp',
        '!! someObject.firstProp',

        'typeof someObject.secondProp == "undefined"',
        'typeof someObject.secondProp === typeof undefined',
        'someObject.secondProp === undefined',
        '! someObject.secondProp',
        '!! someObject.secondProp',

        'typeof someObject.undefinedProp == "undefined"',
        'typeof someObject.undefinedProp === typeof undefined',
        'someObject.undefinedProp === undefined',
        '! someObject.undefinedProp',
        '!! someObject.undefinedProp',

        'typeof notDefined == "undefined"',
        'typeof notDefined === typeof undefined',
        'notDefined === undefined',
        '! notDefined',
        '!! notDefined'
    ];

    var output = document.getElementById('results');
    var result = '';
    for(var t in tests) {
        if( !tests.hasOwnProperty(t) ) continue; // bleh

        try {
            result = eval(tests[t]);
        } catch(ex) {
            result = 'Exception--' + ex;
        }
        console.log(tests[t], result);
        output.innerHTML += "\n" + tests[t] + ": " + result;
    }
})();

和结果:

definedButNotInitialized in window: true
definedAndInitialized in window: false
someObject.firstProp in window: false
someObject.secondProp in window: false
someObject.undefinedProp in window: true
notDefined in window: Exception--ReferenceError: notDefined is not defined
"definedButNotInitialized" in window: false
"definedAndInitialized" in window: true
"someObject.firstProp" in window: false
"someObject.secondProp" in window: false
"someObject.undefinedProp" in window: false
"notDefined" in window: false
typeof definedButNotInitialized == "undefined": true
typeof definedButNotInitialized === typeof undefined: true
definedButNotInitialized === undefined: true
! definedButNotInitialized: true
!! definedButNotInitialized: false
typeof definedAndInitialized == "undefined": false
typeof definedAndInitialized === typeof undefined: false
definedAndInitialized === undefined: false
! definedAndInitialized: false
!! definedAndInitialized: true
typeof someObject.firstProp == "undefined": false
typeof someObject.firstProp === typeof undefined: false
someObject.firstProp === undefined: false
! someObject.firstProp: false
!! someObject.firstProp: true
typeof someObject.secondProp == "undefined": false
typeof someObject.secondProp === typeof undefined: false
someObject.secondProp === undefined: false
! someObject.secondProp: true
!! someObject.secondProp: false
typeof someObject.undefinedProp == "undefined": true
typeof someObject.undefinedProp === typeof undefined: true
someObject.undefinedProp === undefined: true
! someObject.undefinedProp: true
!! someObject.undefinedProp: false
typeof notDefined == "undefined": true
typeof notDefined === typeof undefined: true
notDefined === undefined: Exception--ReferenceError: notDefined is not defined
! notDefined: Exception--ReferenceError: notDefined is not defined
!! notDefined: Exception--ReferenceError: notDefined is not defined

注意在范围包装器中使用 undefined;这不仅可以防止“哦,但是 undefined 可以重新定义”的(不寻常的)情况,而且还可以“帮助”缩小。
P
Peter Mortensen

this article 我读到像 Underscore.js 这样的框架使用这个函数:

function isUndefined(obj){
    return obj === void 0;
}

H
Hrishi

就个人而言,我总是使用以下内容:

var x;
if( x === undefined) {
    //Do something here
}
else {
   //Do something else here
}

window.undefined 属性在所有现代浏览器(JavaScript 1.8.5 或更高版本)中都是不可写的。从 Mozilla 的文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined,我看到:使用 typeof() 的一个原因是,如果尚未定义变量,它不会引发错误。

我更喜欢使用的方法

x === undefined 

因为如果 x 之前没有声明过,它会失败并在我的脸上爆炸,而不是默默地通过/失败。这提醒我 x 未声明。我相信 JavaScript 中使用的所有变量都应该被声明。


您可以使用范围包装器重新声明 undefined(function($, undefined){ /* undefined is 'abc' in here */ })(jQuery, 'abc');,这就是为什么 ppl 抱怨它在技术上不安全,除非您 100% 确定您知道代码在哪里运行。
关于希望未声明的变量爆炸的要点 - typeof 不会发生这种情况。
对于 Windows 版 2021 年 7 月的 Chrome(版本 92.0.4515.107),我尝试了: if ( myVar === undefined )、if ( myVar === 'undefined' )、if ( myVar === void 0) 或 if ( !myVar ) 全部失败!每个案例都会抛出一个未定义的 JavaScript 错误,并有效地返回一个“真”,从而导致分支被采用……解决方案:if (!window.myVar) myVar = false;这就是我所需要的,如果没有包含以前的库将其初始化为 0/false,则将其全局声明为 false。所以仅供参考,最好的解决方案将涉及使用窗口对象!
J
Joseph Gabriel

我知道检查 undefined 的最可靠方法是使用 void 0

这与新旧浏览器兼容,并且在某些情况下不能像 window.undefined 那样被覆盖。

if( myVar === void 0){
    //yup it's undefined
}

这是被低估的,恕我直言,这是检查未定义内容的更好方法。
绝对正确,但我想如果 undefined !== void 0,您可能在所述代码库中遇到其他严重问题。
myVar 之前未声明时,它会引发抛出错误。
P
Peter Mortensen

由于其他答案都没有帮助我,我建议这样做。它在 Internet Explorer 8 中对我有用:

if (typeof variable_name.value === 'undefined') {
    // variable_name is undefined
}

P
Peter Mortensen
// x has not been defined before
if (typeof x === 'undefined') { // Evaluates to true without errors.
   // These statements execute.
}

if (x === undefined) { // Throws a ReferenceError

}

P
Peter Mortensen

与@Thomas Eding 答案相反:

如果我忘记在我的代码中声明 myVar,那么我会得到 myVar is not defined

让我们举一个真实的例子:

我有一个变量名,但我不确定它是否在某处声明。

那么@Anurag 的回答会有所帮助:

var myVariableToCheck = 'myVar';
if (window[myVariableToCheck] === undefined)
    console.log("Not declared or declared, but undefined.");

// Or you can check it directly 
if (window['myVar'] === undefined) 
    console.log("Not declared or declared, but undefined.");

那么,出现这样的 myVar is not defined 错误将是一件 的事情,尤其是当您专门编写“如果我忘记 声明”[强调我的] 时。当我在代码运行之前遇到错误时,我喜欢它。如果您想了解我对您的回答的更多看法,我已经在我的回答下发表了相关评论。
P
Peter Mortensen
    var x;
    if (x === undefined) {
        alert ("I am declared, but not defined.")
    };
    if (typeof y === "undefined") {
        alert ("I am not even declared.")
    };

    /* One more thing to understand: typeof ==='undefined' also checks 
       for if a variable is declared, but no value is assigned. In other 
       words, the variable is declared, but not defined. */

    // Will repeat above logic of x for typeof === 'undefined'
    if (x === undefined) {
        alert ("I am declared, but not defined.")
    };
    /* So typeof === 'undefined' works for both, but x === undefined 
       only works for a variable which is at least declared. */

    /* Say if I try using typeof === undefined (not in quotes) for 
       a variable which is not even declared, we will get run a 
       time error. */

    if (z === undefined) {
        alert ("I am neither declared nor defined.")
    };
    // I got this error for z ReferenceError: z is not defined 

C
Cristian Sanchez

我将它用作函数参数并在函数执行时将其排除在外,这样我就得到了“真正的”未定义。尽管它确实需要您将代码放入函数中。我在阅读 jQuery 源代码时发现了这一点。

undefined = 2;

(function (undefined) {
   console.log(undefined); // prints out undefined
   // and for comparison:
   if (undeclaredvar === undefined) console.log("it works!")
})()

当然,您可以只使用 typeof。但无论如何,我所有的代码通常都在一个包含函数中,所以使用这种方法可能会在这里和那里为我节省一些字节。


如果 var undeclaredvar 确实未声明,它将给出 ReferenceError。这是属性 - 然后它起作用,例如:var undeclaredvar = window.someUndeclaredVar; if (undeclaredvar === undefined) console.log("it works!"). 请在发布之前测试您的示例。