检测未定义的对象属性

Posted

技术标签:

【中文标题】检测未定义的对象属性【英文标题】:Detecting an undefined object property 【发布时间】:2010-09-06 20:25:04 【问题描述】:

检查 javascript 中的对象属性是否未定义的最佳方法是什么?

【问题讨论】:

在此线程中查找最近的答案。在“现代”javascript 中,考虑使用in 运算符:'key' in obj ? 'obj has key property' : 'obj does not have key property' ` 我愿意选择一个新的“正确”答案,如果您想到的答案与当前方法一样完全涵盖旧方法,并且还涉及更现代的选项。 【参考方案1】:

检查属性值是否为特殊值undefined的常用方法是:

if(o.myProperty === undefined) 
  alert("myProperty value is the special value `undefined`");

检查一个对象是否实际上没有这样的属性,因此当你尝试访问它时默认返回undefined

if(!o.hasOwnProperty('myProperty')) 
  alert("myProperty does not exist");

检查与标识符关联的值是否是特殊值undefined如果该标识符尚未声明。注意:此方法是引用 未声明(注意:不同于具有 undefined 的值)标识符的唯一方法,不会出现早期错误:

if(typeof myVariable === 'undefined') 
  alert('myVariable is either the special value `undefined`, or it has not been declared');

在 ECMAScript 5 之前的 JavaScript 版本中,全局对象上名为“undefined”的属性是可写的,因此如果不小心重新定义了 foo === undefined 的简单检查,它可能会出现意外行为。在现代 JavaScript 中,该属性是只读的。

但是,在现代 JavaScript 中,“undefined”不是关键字,因此函数内部的变量可以命名为“undefined”并隐藏全局属性。

如果您担心这种(不太可能的)边缘情况,可以使用 the void operator 来获取特殊的 undefined 值本身:

if(myVariable === void 0) 
  alert("myVariable is the special value `undefined`");

【讨论】:

如果某些东西是空的,它被定义(为空),但你可以结合too检查。上面代码的烦人细节是你不能定义一个函数来检查它,你可以定义函数......但是尝试使用它。 @neu-rah 你为什么不能写一个函数?为什么这样的东西不起作用?它似乎对我有用。有没有我不考虑的情况? jsfiddle.net/djH9N/6 @Zack 您对 isNullorUndefined 的测试没有考虑您调用 isNullOrUndefined(f) 并且 f 未声明(即没有“var f”声明)的情况。 废话,现在有数千票。这是最糟糕的方法。我希望路人看到这条评论并决定检查……咳咳……其他答案。 您现在可以使用obj !== undefinedundefined 曾经是可变的,例如 undefined = 1234 会导致有趣的结果。但是在 Ecmascript 5 之后,它不再是可写的了,所以我们可以使用更简单的版本。 codereadability.com/how-to-check-for-undefined-in-javascript【参考方案2】:

我相信这个话题有很多不正确的答案。与普遍看法相反,“未定义”不是 JavaScript 中的关键字,实际上可以为其分配一个值。

正确代码

执行此测试的最可靠方法是:

if (typeof myVar === "undefined")

这将始终返回正确的结果,甚至可以处理未声明myVar 的情况。

退化代码。不要使用。

var undefined = false;  // Shockingly, this is completely legal!
if (myVar === undefined) 
    alert("You have been misled. Run away!");

另外,myVar === undefined 将在 myVar 未声明的情况下引发错误。

【讨论】:

除了 Marks cmets,我不明白:“myVar === undefined 在 myVar 未声明的情况下会引发错误。” - 为什么这很糟糕?如果我引用未声明的变量,为什么我不想出现错误? 另外请记住,您始终可以使用void 0 来获取undefined 指向的值。所以你可以做if (myVar === void 0)0 并不特别,您可以在其中放置任何表达式。 在现代浏览器(FF4+、IE9+、Chrome 未知)中,无法再修改undefined。 MDN: undefined 这个答案也不正确。问题是关于未定义的对象属性,而不是未定义的变量。有显着差异。例如,if (obj.field === undefined) 是完全合理的。我认为有人做var undefined = false; 的风险被高估了。如果您想防止因糟糕的编程而导致的所有此类副作用,您将不得不进行不合理的防御性编程。 有趣的是,人们建议使用这些愚蠢且容易出错的 hack 来避免隐藏的 undefined(这只能由糟糕的开发人员完成),但他们却愉快地使用其他全局标识符,这些标识符也可能是阴影。奇怪。真是奇怪。【参考方案3】:

尽管这里有许多其他答案强烈推荐,typeof 是一个糟糕的选择。它永远不应该用于检查变量是否具有值undefined,因为它作为对值undefined 和变量是否存在的组合检查。在绝大多数情况下,您知道变量何时存在,如果您在变量名或字符串文字 'undefined' 中输入错误,typeof 只会引入静默失败的可能性。

var snapshot = …;

if (typeof snaposhot === 'undefined') 
    //         ^
    // misspelled¹ – this will never run, but it won’t throw an error!

var foo = …;

if (typeof foo === 'undefned') 
    //                   ^
    // misspelled – this will never run, but it won’t throw an error!

因此,除非您进行特征检测²,否则不确定给定名称是否在范围内(例如检查 typeof module !== 'undefined' 作为特定于 CommonJS 环境的代码中的一个步骤),typeof 在使用时是一个有害的选择在一个变量上,正确的选择是直接比较值:

var foo = …;

if (foo === undefined) 
    ⋮

对此的一些常见误解包括:

读取“未初始化”变量(var foo)或参数(function bar(foo) … ,称为bar())将失败。这根本不是真的——没有显式初始化的变量和没有给定值的参数总是变成undefined,并且总是在范围内。

undefined 可以被覆盖。 undefined 确实不是关键字,但它只读且不可配置的。尽管它们的非关键字状态(ObjectMathNaN...)和实用代码通常不是在积极的恶意环境中编写的,但您可能无法避免使用其他内置插件,所以这不是担心undefined 的充分理由。 (但如果您正在编写代码生成器,请随意使用void 0。)

了解变量的工作原理之后,是时候解决实际问题了:对象属性。没有理由将typeof 用于对象属性。前面关于特征检测的例外在这里不适用——typeof 仅对变量有特殊行为,引用对象属性的表达式不是变量。

这个:

if (typeof foo.bar === 'undefined') 
    ⋮

总是完全等价于这个³:

if (foo.bar === undefined) 
    ⋮

并考虑到上面的建议,以避免让读者混淆你为什么使用typeof,因为使用=== 来检查是否相等是最有意义的,因为它可以被重构为检查稍后变量的值,因为它看起来更好,您也应该始终在此处使用=== undefined³

在对象属性方面需要考虑的其他一点是您是否真的要检查undefined。给定的属性名称可以在对象上不存在(读取时产生值undefined),以值undefined 出现在对象本身上,以值undefined 出现在对象的原型上,或者出现在任何一个上那些具有非undefined 值的人。 'key' in obj 会告诉你一个键是否在对象的原型链上,Object.prototype.hasOwnProperty.call(obj, 'key') 会告诉你它是否直接在对象上。不过,我不会在这个答案中详细介绍原型和将对象用作字符串键映射,因为它主要是为了反驳其他答案中的所有坏建议,而不管原始问题的可能解释如何。阅读object prototypes on MDN了解更多信息!

¹ 示例变量名的选择异常?这是来自 Firefox 的 NoScript 扩展的真正死代码。² 不过,不要假设不知道范围内的内容通常是可以接受的。滥用动态范围导致的额外漏洞:Project Zero 1225³ 再次假设 ES5+ 环境,undefined 引用全局对象的 undefined 属性。

【讨论】:

@BenjaminGruenbaum 确实,但完全具有误导性。任何非默认上下文都可以定义自己的undefined,隐藏默认上下文。对于大多数实际目的而言,这与覆盖它具有相同的效果。 @blgt 这太偏执了,与任何实际操作无关。每个上下文都可以覆盖 console.log,重新定义 Array 原型方法,甚至覆盖 Function.prototype.call` 挂钩,并在每次调用 JavaScript 中的函数时进行更改。防止这种情况是非常偏执且相当愚蠢的。就像我(和 minitech)说的那样,您可以使用 void 0 与 undefined 进行比较,但又一次 - 这是愚蠢和矫枉过正。 我希望我有不止一张赞成票。这是最正确的答案。我真的不想在代码中看到typeof something === "undefined") 这确实应该是公认的答案。这是最彻底和最新的。 任何非默认上下文也可以覆盖,例如,Math、或Object、或setTimeout,或者您希望在默认情况下在全局范围内找到的任何内容。跨度> 【参考方案4】:

在 JavaScript 中有 nullundefined。它们有不同的含义。

undefined 表示变量值尚未定义;不知道值是多少。 null 表示定义了变量值并设置为null(没有值)。

Marijn Haverbeke 在他的免费在线书籍“Eloquent JavaScript”(强调我的)中指出:

还有一个类似的值,null,意思是'这个值被定义了,但是它没有值'。 undefined 和 null 之间的含义差异主要是学术性的,通常不是很有趣。 在实际程序中,经常需要检查某物是否“有价值”。在这些情况下,可以使用表达式 something == undefined,因为即使它们的值不完全相同,null == undefined 也会产生 true。

所以,我想检查某些内容是否未定义的最佳方法是:

if (something == undefined)

对象属性应该以同样的方式工作。

var person = 
    name: "John",
    age: 28,
    sex: "male"
;

alert(person.name); // "John"
alert(person.fakeVariable); // undefined

【讨论】:

if (something == undefined) 最好写成 if (something === undefined) 应该指出,这并不完全安全。 undefined 只是一个可以由用户重新分配的变量:编写 undefined = 'a'; 将导致您的代码不再执行您认为的操作。使用typeof 更好,也适用于尚未声明的变量(不仅仅是属性)。 如果某个东西是一个未定义的全局变量,(something == undefined) 会引发 javascript 错误。 这样做的问题是,如果 var a = null 则 a == undefined 的计算结果为 true,即使 a 已被确定定义。 对“Eloquent Javascript”注释的这种解释是向后。如果您真的只想检查未定义,则建议的代码将不起作用(它还将检测已定义的条件但尚未关联任何值[即空])。空值。建议的代码“if (something == undefined) ...”检查 both undefined 和 null(未设置值),即它被解释为“if ((something is undefined) OR (something is null)) ...”作者的意思是,通常您真正想要的是检查 both undefined 和 null。【参考方案5】:

这是什么意思:“未定义的对象属性”

实际上它可能意味着两个完全不同的东西!首先,它可以表示对象中从未定义过的属性,其次,它可以表示具有未定义值的属性。我们来看看这段代码:

var o =  a: undefined 

o.a 是否未定义?是的!它的值是未定义的。 o.b 未定义吗?当然!根本没有属性'b'!好的,现在看看不同的方法在这两种情况下的表现:

typeof o.a == 'undefined' // true
typeof o.b == 'undefined' // true
o.a === undefined // true
o.b === undefined // true
'a' in o // true
'b' in o // false

我们可以清楚地看到typeof obj.prop == 'undefined'obj.prop === undefined 是等价的,它们并没有区分那些不同的情况。而'prop' in obj 可以检测到一个属性根本没有定义并且不关注可能未定义的属性值的情况。

那该怎么办?

1) 您想知道某个属性是否未按第一个含义或第二个含义定义(最典型的情况)。

obj.prop === undefined // IMHO, see "final fight" below

2) 你只想知道对象是否有一些属性而不关心它的值。

'prop' in obj

注意事项:

您不能同时检查一个对象及其属性。例如,如果未定义 x,则此 x.a === undefined 或此 typeof x.a == 'undefined' 引发 ReferenceError: x is not defined。 变量undefined 是一个全局变量(所以实际上它在浏览器中是window.undefined)。它从 ECMAScript 1st Edition 开始就受到支持,并且从 ECMAScript 5 开始它是只读的。因此,在现代浏览器中,它不能重新定义为 true,因为许多作者喜欢用这些来吓唬我们,但对于旧版浏览器来说,这仍然是正确的。

最终决战:obj.prop === undefined vs typeof obj.prop == 'undefined'

obj.prop === undefined 的加号:

短了一些,看起来更漂亮了 如果你拼错了undefined,JavaScript 引擎会给你一个错误

obj.prop === undefined 的减号:

undefined 可以在旧浏览器中被覆盖

typeof obj.prop == 'undefined' 的加号:

真的是万能的!它适用于新旧浏览器。

typeof obj.prop == 'undefined' 的减号:

'undefned' (拼写错误) 这里只是一个字符串常量,所以如果你像我刚才那样拼错了,JavaScript 引擎将无法帮助你。

更新(用于服务器端 JavaScript):

Node.js 支持全局变量 undefinedglobal.undefined(它也可以在没有 'global' 前缀的情况下使用)。我不知道服务器端 JavaScript 的其他实现。

【讨论】:

@Bergi 感谢您的评论。我已经更正了我的答案。在我的辩护中,我可以说目前(截至 v.0.10.18)official Node.js documentation 没有提及 undefined 作为global 的成员。同样,console.log(global);for (var key in global) ... 都没有将 undefined 显示为 global 的成员。但是像'undefined' in global 这样的测试显示相反。 它不需要额外的文档,因为it's in the EcmaScript spec,这也表明[[Enumerable]] 是错误的:-) 关于Minuses of typeof obj.prop == 'undefined',这可以通过写成typeof obj.prop == typeof undefined来避免。这也提供了非常好的对称性。 @hlovdal:与obj.prop === undefined 相比,这完全没有意义。 当我们对问题标题 Detecting an undefined property“ 是真实的,而不是对第一句(“检查是否未定义......”),你回答if ('foo' in o)......你的答案确实是这里的第一个正确答案。几乎所有其他人都只是回答这句话。【参考方案6】:

问题归结为三种情况:

    对象有属性,但值不是undefined。 对象具有属性,其值为undefined。 对象没有属性。

这告诉我们一些我认为很重要的事情:

未定义成员和具有未定义值的已定义成员之间存在差异。

但不幸的是,typeof obj.foo 没有告诉我们三个案例中的哪一个。但是我们可以将它与"foo" in obj 结合起来以区分情况。

                               |  typeof obj.x === 'undefined' | !("x" in obj)
1.                      x:1  |  false                        | false
2.     x : (function())()  |  true                         | false
3.                           |  true                         | true

值得注意的是,null 条目的这些测试也相同

                               |  typeof obj.x === 'undefined' | !("x" in obj)
                     x:null  |  false                        | false

我认为在某些情况下,检查属性是否存在比检查它是否未定义更有意义(并且更清晰),并且这种检查不同的唯一情况是情况 2,即对象中的实际条目具有未定义值的罕见情况。

例如:我刚刚重构了一堆代码,其中包含一堆检查对象是否具有给定属性的代码。

if( typeof blob.x != 'undefined' )   fn(blob.x); 

在没有检查未定义的情况下编写时更清晰。

if( "x" in blob )  fn(blob.x); 

但正如已经提到的,这些并不完全相同(但对于我的需求来说已经足够好了)。

【讨论】:

嗨迈克尔。很好的建议,我认为它确实让事情变得更清洁。然而,我发现的一个问题是使用 !带有“in”的运算符。你必须说if (!("x" in blob)) ,括号括起来,因为!运算符优先于“in”。希望对某人有所帮助。 对不起,迈克尔,但鉴于原始问题,这是不正确的,或者至少具有误导性。 'in' 不足以测试对象属性是否具有未定义的类型。为了证明,请看这个小提琴:jsfiddle.net/CsLKJ/4 这两个代码部分做不同的事情! a = b: undefined给出的考虑和反对;然后是typeof a.b === typeof a.c === 'undefined''b' in a!('c' in a) +1。 OP 没有明确说明该属性是否存在并具有值 undefined,或者该属性本身是否未定义(即不存在)。 我建议将第一个表中的点 (2.) 更改为 x : undefined 或至少将其添加为表中 (2.) 的另一种选择 - 我不得不考虑片刻意识到点 (2.) 的计算结果为 undefined(尽管您稍后会提到)。【参考方案7】:
if ( typeof( something ) == "undefined") 

这对我有用,而其他人没有。

【讨论】:

括号是不必要的,因为 typeof 是一个运算符 但它们使检查的内容更加清晰。否则它可能被读作typeof (something == "undefined") 如果你需要括号,那么你应该学习JS中的运算符优先级:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 括号之所以有用正是因为你不需要在JS中学习运算符优先级,也不需要推测未来的维护程序员是否需要学习JS中的运算符优先级。 括号有助于澄清事情。但在这种情况下,它们只是让操作符看起来像一个函数。毫无疑问,这阐明了程序员的意图。但是如果你不确定运算符的优先级,你应该把它写成(typeof something) === "undefined"【参考方案8】:

我不确定使用 ===typeof 的起源来自哪里,作为惯例,我看到它在许多库中使用,但是 typeof 运算符返回一个字符串文字,我们预先知道这一点,那你为什么还要输入检查呢?

typeof x;                      // some string literal "string", "object", "undefined"
if (typeof x === "string")    // === is redundant because we already know typeof returns a string literal
if (typeof x == "string")     // sufficient

【讨论】:

伟大的埃里克。检查类型是否也会影响性能? @Simon:恰恰相反——人们可以预期在 '===' 的情况下避免强制会导致轻微的性能损失。快速而肮脏的测试表明,在 FF5.0.1 下,'===' 比 '==' 快 5% 更彻底的测试表明,在 FF、IE 和 Chrome 下,'==' 或多或少比 '===' (5-10%) 快,而 Opera 在全部:jsperf.com/triple-equals-vs-twice-equals/6 使用== 仍然需要至少进行类型检查 - 解释器无法在不知道它们的类型之前比较两个操作数。 ===== 少一个字符 :)【参考方案9】:

我没有看到(希望我没有错过)任何人在财产之前检查该对象。所以,这是最短且最有效的(虽然不一定是最清楚的):

if (obj && obj.prop) 
  // Do something;

如果 obj 或 obj.prop 为 undefined、null 或“falsy”,则 if 语句不会执行代码块。这通常是大多数代码块语句(在 JavaScript 中)中的期望行为。

更新:(2021 年 7 月 2 日)

最新版本的 JavaScript 引入了一个新的运算符 可选链:?.

这可能是检查对象属性是否存在的最明确和最有效的方法。

参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

【讨论】:

如果你想知道为什么会这样:Javascript: Logical Operators and truthy / falsy 如果要将属性分配给已定义的变量,不为空也不为假,否则使用一些默认值,您可以使用:var x = obj && obj.prop || 'default'; 我相信问题在于明确检查未定义。您的条件检查 JS 的所有错误值。【参考方案10】:

从相关问题交叉发布my answerHow can I check for "undefined" in JavaScript?

具体到这个问题,请参阅someObject.<whatever> 的测试用例。


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

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

参考代码:

(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

【讨论】:

【参考方案11】:

如果你这样做

if (myvar == undefined )
 
    alert('var does not exists or is not initialized');

当变量myvar不存在时会失败,因为myvar没有定义,所以脚本坏了,测试没有效果。

由于窗口对象在函数之外具有全局范围(默认对象),因此声明将“附加”到窗口对象。

例如:

var myvar = 'test';

全局变量myvarwindow.myvarwindow['myvar']

相同

为避免在全局变量存在时测试错误,您最好使用:

if(window.myvar == undefined )
 
    alert('var does not exists or is not initialized');

变量是否真的存在无关紧要,它的值不正确。否则用 undefined 初始化变量是愚蠢的,最好使用值 false 来初始化。当您知道您声明的所有变量都以 false 初始化时,您可以简单地检查其类型或依靠 !window.myvar 来检查它是否具有正确/有效的值。因此,即使未定义变量,!window.myvar 对于myvar = undefinedmyvar = falsemyvar = 0 也是相同的。

当您期望特定类型时,请测试变量的类型。要加快测试条件,您最好这样做:

if( !window.myvar || typeof window.myvar != 'string' )

    alert('var does not exists or is not type of string');

当第一个简单条件为真时,解释器会跳过接下来的测试。

最好使用变量的实例/对象来检查它是否获得了有效值。它更稳定,是一种更好的编程方式。

(y)

【讨论】:

【参考方案12】:

在文章Exploring the Abyss of Null and Undefined in JavaScript 我读到像Underscore.js这样的框架使用这个功能:

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

【讨论】:

void 0 只是写undefined 的一种简短方式(因为这是 void 后跟任何表达式返回的内容),它节省了 3 个字符。它也可以做var a; return obj === a;,但这是另一个字符。 :-) void 是保留字,而undefined 不是,即默认情况下undefined 等于void 0,您可以为undefined 赋值,例如undefined = 1234. isUndefined(obj):16 个字符。 obj === void 0:14 个字符。 '不多说了。【参考方案13】:

任何东西都没有在 JavaScript 中定义,是 undefined,不管它是 Object/Array 中的属性还是只是一个简单的变量...

JavaScript 有typeof,它可以很容易地检测到未定义的变量。

只需检查 typeof whatever === 'undefined' 是否会返回一个布尔值。

AngularJs v.1x 中著名的函数isUndefined() 就是这样写的:

function isUndefined(value) return typeof value === 'undefined'; 

所以当你看到函数接收一个值时,如果该值已定义,它将返回false,否则对于未定义的值,返回true

那么让我们看看当我们传递值时会产生什么结果,包括像下面这样的对象属性,这是我们拥有的变量列表:

var *** = ;
***.javascipt = 'javascript';
var today;
var self = this;
var num = 8;
var list = [1, 2, 3, 4, 5];
var y = null;

我们检查它们如下,您可以在它们前面看到结果作为评论:

isUndefined(***); //false
isUndefined(***.javascipt); //false
isUndefined(today); //true
isUndefined(self); //false
isUndefined(num); //false
isUndefined(list); //false
isUndefined(y); //false
isUndefined(***.java); //true
isUndefined(***.php); //true
isUndefined(*** && ***.css); //true

如您所见,我们可以在代码中使用类似这样的内容来检查任何内容,如前所述,您可以在代码中简单地使用 typeof,但如果您一遍又一遍地使用它,请创建一个类似 angular 示例的函数我按照 DRY 代码模式分享并继续重复使用。

还有一件事,要检查实际应用程序中对象的属性,即使该对象是否存在也不确定,请先检查该对象是否存在。

如果您检查对象的属性并且该对象不存在,则会抛出错误并停止整个应用程序的运行。

isUndefined(x.css);
VM808:2 Uncaught ReferenceError: x is not defined(…)

如此简单,您可以像下面这样将 if 语句包裹起来:

if(typeof x !== 'undefined') 
  //do something

这也等于 Angular 1.x 中的 isDefined...

function isDefined(value) return typeof value !== 'undefined';

其他 javascript 框架(如 underscore)也有类似的定义检查,但如果您还没有使用任何框架,我建议您使用 typeof

我还添加了来自 MDN 的这一部分,其中包含有关 typeof、undefined 和 void(0) 的有用信息。

严格相等和未定义 您可以使用未定义和严格相等和不等运算符来确定变量是否具有 一个值。在下面的代码中,变量 x 没有定义,并且 if 语句的计算结果为 true。

var x;
if (x === undefined) 
   // these statements execute

else 
   // these statements do not execute

注意:严格相等运算符而不是标准相等 此处必须使用运算符,因为 x == undefined 还会检查是否 x 为空,而严格相等则不是。 null 不等于 不明确的。有关详细信息,请参阅比较运算符。


Typeof 运算符和未定义 或者,可以使用 typeof:

var x;
if (typeof x === 'undefined') 
   // these statements execute

使用 typeof 的一个原因是,如果 变量尚未声明。

// x has not been declared before
if (typeof x === 'undefined')  // evaluates to true without errors
   // these statements execute


if (x === undefined)  // throws a ReferenceError


但是,应该避免这种技术。 JavaScript 是一个 静态范围的语言,所以知道变量是否被声明可以 通过查看它是否在封闭上下文中声明来阅读。这 唯一的例外是全局范围,但全局范围必须 全局对象,因此检查变量中是否存在 全局上下文可以通过检查属性的存在来完成 全局对象(例如使用 in 运算符)。


空运算符和未定义

void 运算符是第三种选择。

var x;
if (x === void 0) 
   // these statements execute


// y has not been declared before
if (y === void 0) 
   // throws a ReferenceError (in contrast to `typeof`)

更多 > here

【讨论】:

【参考方案14】:

'if (window.x) ' 是错误安全的

您很可能想要if (window.x)。即使未声明 x (var x;),此检查也是安全的 - 浏览器不会抛出错误。

示例:我想知道我的浏览器是否支持 History API

if (window.history) 
    history.call_some_function();

这是如何工作的:

window 是一个将所有全局变量作为其成员的对象,尝试访问不存在的成员是合法的。如果 x 尚未声明或尚未设置,则 window.x 返回 undefined。当 if() 评估它时,undefined 会导致 false

【讨论】:

但是如果你在 Node 中运行呢? typeof history != 'undefined' 实际上在两个系统中都有效。【参考方案15】:

读完这篇文章,我很惊讶我没有看到这个。我找到了多种适用于此的算法。

从未定义

如果一个对象的值从未被定义,如果它被定义为nullundefined,这将阻止返回true。如果您希望为设置为 undefined 的值返回 true,这将很有帮助

if(obj.prop === void 0) console.log("The value has never been defined");

定义为未定义或从未定义

如果您希望它的结果为 true 对于使用 undefined 值定义或从未定义的值,您可以简单地使用 === undefined

if(obj.prop === undefined) console.log("The value is defined as undefined, or never defined");

定义为假值、未定义、空值或从未定义。

通常,人们要求我提供一种算法来确定一个值是假的、undefined 还是 null。以下工作。

if(obj.prop == false || obj.prop === null || obj.prop === undefined) 
    console.log("The value is falsy, null, or undefined");

【讨论】:

我觉得你可以把最后一个例子换成if (!obj.prop) @StijndeWitt,你可以,我写这篇文章的时候非常缺乏经验,而且我的英语似乎也同样糟糕,但是,没有任何 incorrect 的内容回答 var obj = foo: undefined; obj.foo === void 0 -> true。那“从未定义为undefined”是怎么回事?这是错误的。 @PatrickRoberts 你是对的。当我在 2015 年 2 月(在 ES6 之前)写这个答案时,我概述的第一个选项确实有效,但它现在已经过时了。【参考方案16】:

ECMAScript 10 引入了一个新功能 - 可选链接,您可以使用它来使用对象的属性,只有当对象被这样定义时:

const userPhone = user?.contactDetails?.phone;

只有在定义了 user 和 contactDetails 时才会引用 phone 属性。

参考。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

【讨论】:

我以前用过很多lodash的get函数,访问这类对象很方便,但是新的可选链覆盖了_.get的大部分用法【参考方案17】:
"propertyName" in obj //-> true | false

【讨论】:

【参考方案18】:

解决方案不正确。在 JavaScript 中,

null == undefined

将返回 true,因为它们都被“强制转换”为布尔值并且为 false。正确的方法是检查

if (something === undefined)

这是身份运算符...

【讨论】:

要清楚,=== 是类型相等 +(原始相等 | 对象标识),其中原语包括字符串。如果有人将=== 视为身份运算符,我认为大多数人认为'abab'.slice(0,2) === 'abab'.slice(2) 不直观。 错了。如果尚未创建变量,则会引发错误。不应该投赞成票。请改用 typeof。 什么解决方案?可以直接链接吗?【参考方案19】:

为了简洁起见,与void 0 比较。

if (foo !== void 0)

不像if (typeof foo !== 'undefined')那么冗长

【讨论】:

但如果 foo 未声明,它会抛出 ReferenceError。 @daniel1426:所以如果你的代码有错误,你想隐藏它而不是修复它?不是一个好方法,IMO。 这不是用来隐藏错误的。这是检测环境属性以定义 polyfill 的常用方法。例如: if( typeof Promise === 'undefined' ) /* 定义 Promise */ 【参考方案20】:

您可以使用以下代码获取所有未定义路径的数组。

 function getAllUndefined(object) 

        function convertPath(arr, key) 
            var path = "";
            for (var i = 1; i < arr.length; i++) 

                path += arr[i] + "->";
            
            path += key;
            return path;
        


        var stack = [];
        var saveUndefined= [];
        function getUndefiend(obj, key) 

            var t = typeof obj;
            switch (t) 
                case "object":
                    if (t === null) 
                        return false;
                    
                    break;
                case "string":
                case "number":
                case "boolean":
                case "null":
                    return false;
                default:
                    return true;
            
            stack.push(key);
            for (k in obj) 
                if (obj.hasOwnProperty(k)) 
                    v = getUndefiend(obj[k], k);
                    if (v) 
                        saveUndefined.push(convertPath(stack, k));
                    
                
            
            stack.pop();

        

        getUndefiend(
            "": object
        , "");
        return saveUndefined;
    

jsFiddle链接

【讨论】:

虽然它不会影响您的代码的有效性,但您有一个错字:getUndefiend 应该是 getUndefined【参考方案21】:

有一种很好的优雅方法可以将已定义的属性分配给新变量(如果已定义),或者将默认值分配给它作为未定义的后备。

var a = obj.prop || defaultValue;

如果你有一个函数是合适的,它接收一个额外的配置属性:

var yourFunction = function(config)

   this.config = config || ;
   this.yourConfigValue = config.yourConfigValue || 1;
   console.log(this.yourConfigValue);

正在执行

yourFunction(yourConfigValue:2);
//=> 2

yourFunction();
//=> 1

yourFunction(otherProperty:5);
//=> 1

【讨论】:

【参考方案22】:

所有答案都不完整。这是知道有一个属性“定义为未定义”的正确方法:

var hasUndefinedProperty = function hasUndefinedProperty(obj, prop)
  return ((prop in obj) && (typeof obj[prop] == 'undefined'));
;

例子:

var a =  b : 1, e : null ;
a.c = a.d;

hasUndefinedProperty(a, 'b'); // false: b is defined as 1
hasUndefinedProperty(a, 'c'); // true: c is defined as undefined
hasUndefinedProperty(a, 'd'); // false: d is undefined
hasUndefinedProperty(a, 'e'); // false: e is defined as null

// And now...
delete a.c ;
hasUndefinedProperty(a, 'c'); // false: c is undefined

太糟糕了,这是正确的答案,却被错误的答案所掩盖>_

所以,路过的人,我免费送你未定义的!!

var undefined ; undefined ; // undefined
().a ;                    // undefined
[].a ;                      // undefined
''.a ;                      // undefined
(function()()) ;          // undefined
void(0) ;                   // undefined
eval() ;                    // undefined
1..a ;                      // undefined
/a/.a ;                     // undefined
(true).a ;                  // undefined

【讨论】:

【参考方案23】:

这是我的情况:

我正在使用 REST 调用的结果。结果应从 JSON 解析为 JavaScript 对象。

我需要捍卫一个错误。如果 REST 调用的参数不正确,就用户指定的参数错误而言,REST 调用返回基本上是空的。

在使用这篇文章来帮助我防御这一点时,我尝试了这个:

if( typeof restResult.data[0] === "undefined" )  throw  "Some error"; 

对于我的情况,如果 restResult.data[0] === "object",那么我可以安全地开始检查其余成员。如果未定义,则抛出上述错误。

我的意思是,就我的情况而言,这篇文章中之前的所有建议都不起作用。我不是说我是对的,每个人都是错的。我根本不是 JavaScript 大师,但希望这会对某人有所帮助。

【讨论】:

您的typeof 守卫实际上并不能防范直接比较无法处理的任何事情。如果restResult 未定义或未声明,它仍然会抛出。 在您的情况下,您可以更简单地检查数组是否为空:if(!restResult.data.length) throw "Some error"; 【参考方案24】:

通过 cmets,对于那些想要检查两者的人来说,它是未定义还是它的值为 null:

//Just in JavaScript
var s; // Undefined
if (typeof s == "undefined" || s === null)
    alert('either it is undefined or value is null')

如果您使用的是 jQuery 库,那么 jQuery.isEmptyObject() 就可以满足这两种情况,

var s; // Undefined
jQuery.isEmptyObject(s); // Will return true;

s = null; // Defined as null
jQuery.isEmptyObject(s); // Will return true;

//Usage
if (jQuery.isEmptyObject(s)) 
    alert('Either variable:s is undefined or its value is null');
 else 
     alert('variable:s has value ' + s);


s = 'something'; // Defined with some value
jQuery.isEmptyObject(s); // Will return false;

【讨论】:

jQuery 还将处理不同 JavaScript API 的任何跨浏览器兼容性问题。【参考方案25】:

如果您使用的是 Angular:

angular.isUndefined(obj)
angular.isUndefined(obj.prop)

下划线.js:

_.isUndefined(obj) 
_.isUndefined(obj.prop) 

【讨论】:

如何将1 添加到变量x?我需要下划线还是 jQuery? (令人惊讶的是,人们甚至会使用库进行最基本的操作,例如 typeof 检查)【参考方案26】:

我在这里为那些期待奇怪答案的人提供了三种方法:

function isUndefined1(val) 
    try 
        val.a;
     catch (e) 
        return /undefined/.test(e.message);
    
    return false;


function isUndefined2(val) 
    return !val && val+'' === 'undefined';


function isUndefined3(val) 
    const defaultVal = ;
    return ((input = defaultVal) => input === defaultVal)(val);


function test(func)
    console.group(`test start :`+func.name);
    console.log(func(undefined));
    console.log(func(null));
    console.log(func(1));
    console.log(func("1"));
    console.log(func(0));
    console.log(func());
    console.log(func(function ()  ));
    console.groupEnd();

test(isUndefined1);
test(isUndefined2);
test(isUndefined3);

isUn​​defined1:

尝试获取输入值的属性,并检查错误信息是否存在。如果输入值未定义,则错误消息将是Uncaught TypeError: Cannot read property 'b' of undefined

isUn​​defined2:

将输入值转换为字符串以与"undefined" 进行比较,并确保其为负值。

isUn​​defined3:

在 JavaScript 中,当输入值恰好是 undefined 时,可选参数起作用。

【讨论】:

【参考方案27】:

有一个非常简单的方法。

您可以使用可选链接

x = prop:name:"sajad"

console.log(x.prop?.name) // Output is: "sajad"
console.log(x.prop?.lastName) // Output is: undefined

if(x.prop?.lastName) // The result of this 'if' statement is false and is not throwing an error

您甚至可以对函数或数组使用可选链接。

截至 2020 年年中,这并未普遍实施。查看https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining的文档

【讨论】:

这正是我想要的。谢谢!【参考方案28】:

我使用if (this.variable) 来测试它是否已定义。一个简单的if (variable)、recommended in a previous answer 对我来说失败了。

事实证明,它只有在变量是某个对象的字段时才有效,obj.someField 检查它是否在字典中定义。但是我们可以使用thiswindow 作为字典对象,因为据我所知,任何变量都是当前窗口中的一个字段。因此这里是一个测试:

if (this.abc) 
    alert("defined"); 
else 
    alert("undefined");

abc = "abc";
if (this.abc) 
    alert("defined"); 
else 
    alert("undefined");

首先检测变量abc未定义,初始化后定义。

【讨论】:

【参考方案29】:
function isUnset(inp) 
  return (typeof inp === 'undefined')

如果设置了变量,则返回 false,如果未定义,则返回 true。

然后使用:

if (isUnset(var)) 
  // initialize variable here

【讨论】:

没有。不要这样做。只需要 very simple test 就可以证明您无法在函数中有意义地包装 typeof 测试。令人惊讶的是,有 4 人对此表示赞同。 -1.【参考方案30】:

我想向您展示我正在使用的东西来保护undefined 变量:

Object.defineProperty(window, 'undefined', );

这禁止任何人更改window.undefined 值,从而破坏基于该变量的代码。如果使用"use strict",任何试图改变其值的东西都会以错误结束,否则会被忽略。

【讨论】:

以上是关于检测未定义的对象属性的主要内容,如果未能解决你的问题,请参考以下文章

Yolov5自定义对象检测模型未加载

检查对象属性时与未定义或“未定义”的比较。有什么不同?

Vue 自定义指令 - 对象属性未定义

即使对象已定义,也无法读取“未定义”的属性! [反应]

对象属性的双重分配导致未定义的属性[重复]

SCRIPT5009:“JSON”在 IE 10 中未定义属性“$”的值为 null 或未定义,不是函数对象