检测未定义的对象属性

IT技术 javascript object undefined object-property
2021-02-07 20:37:53

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

6个回答

检查属性值是否为特殊值的常用方法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”并隐藏全局属性。

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

if(myVariable === void 0) {
  alert("myVariable is the special value `undefined`");
}
@neu-rah 为什么你不能写一个函数?为什么这样的事情行不通?它似乎对我有用。有没有我不考虑的情况?jsfiddle.net/djH9N/6
2021-03-28 20:37:53
废话,现在有数千票。这是最糟糕的方法。我希望路人看到这条评论并决定检查......嗯......其他答案。
2021-03-31 20:37:53
obj !== undefined现在就可以使用undefined曾经是可变的,就像undefined = 1234会导致有趣的结果一样。但是在 Ecmascript 5 之后,它不再是可写的,所以我们可以使用更简单的版本。codereadability.com/how-to-check-for-undefined-in-javascript
2021-04-01 20:37:53
@Zack 你对 isNullorUndefined 的测试没有考虑你调用 isNullOrUndefined(f) 并且 f 未声明的情况(即没有“var f”声明的情况)。
2021-04-03 20:37:53
如果某些内容为空,则将其定义(为空),但您可以结合使用 too 检查。上面代码烦人的细节是你不能定义一个函数来检查它,你可以定义函数......但尝试使用它。
2021-04-04 20:37:53

我相信这个话题有很多不正确的答案。与普遍看法相反,“undefined”不是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 评论之外,我还没有明白:“myVar === undefined 会在 myVar 未声明的情况下引发错误。” - 为什么这很糟糕?为什么我想要,如果我引用未声明的变量有一个错误?
2021-03-12 20:37:53
有趣的是,人们建议使用这些愚蠢且容易出错的 hack 来避免被屏蔽undefined(这只能由糟糕的开发人员完成),但他们却乐于使用其他也可能被屏蔽的全局标识符。奇怪。只是奇怪。
2021-03-13 20:37:53
在现代浏览器(FF4+、IE9+、Chrome 未知)中,不再可能修改undefined. MDN:未定义
2021-04-04 20:37:53
这个答案也是不正确的。问题是关于未定义的对象属性,而不是未定义的变量。有显着差异。例如,这样做是完全合理的if (obj.field === undefined)我认为某人这样做的风险var undefined = false;被高估了。如果您想防止由糟糕的编程引起的所有此类副作用,您将不得不进行不合理的防御性编程。
2021-04-06 20:37:53
还请记住,您始终void 0可以获取undefined指向的值所以你可以这样做if (myVar === void 0)0没有特别的,你可以随便把任何表达中。
2021-04-07 20:37:53

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

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) { … },称为 as bar()) 将失败。这根本不是真的——没有显式初始化的变量和没有给定值的参数总是变成undefined,并且总是在范围内。

  • undefined可以被覆盖。这确实undefined不是关键字,但它只读且不可配置的。还有其他内置程序,尽管它们处于非关键字状态(Object, Math, NaN...),但您可能不会避免而且实用代码通常不是在恶意的环境中编写的,因此这不是担心 的好理由undefined(但如果您正在编写代码生成器,请随意使用void 0。)

随着变量如何工作,是时候解决实际问题了:对象属性。没有理由使用typeof对象属性。早期关于特征检测的例外不适用于这里——typeof仅对变量有特殊行为,引用对象属性的表达式不是变量。

这个:

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

始终完全等同于this³:

if (foo.bar === undefined) {
    ⋮
}

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

涉及对象属性时要考虑的另一件事是您是否真的想要检查undefined给定的属性名称可以不存在于对象上(undefined读取时产生值),以 value出现在对象本身上,以 valueundefined出现在对象的原型上undefined,或出现在具有非undefined值的任何一个上'key' in obj会告诉你一个键是否在对象原型链上的任何地方,并Object.prototype.hasOwnProperty.call(obj, 'key')会告诉你它是否直接在对象上。不过,我不会在这个关于原型和使用对象作为字符串键映射的答案中详细介绍,因为它主要是为了反驳其他答案中的所有错误建议,而不管原始问题的可能解释如何。继续阅读MDN 上的对象原型了解更多!

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

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

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

  • undefined表示变量值尚未定义;不知道它的value是什么。
  • null表示变量值已定义并设置为 null(没有值)。

Marijn Haverbeke 在他的免费在线书籍“ Eloquent JavaScript ”(重点是我的)中说:

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

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

if (something == undefined)

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

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

alert(person.name); // "John"
alert(person.fakeVariable); // undefined
需要指出的是,这并不完全安全。undefined只是一个可以由用户重新分配的变量:编写undefined = 'a';将导致您的代码不再按照您的想法执行。使用typeof更好,也适用于尚未声明的变量(不仅仅是属性)。
2021-03-17 20:37:53
这样做的问题是,如果 var a = null 则 a == undefined 评估为真,即使 a 肯定是定义的。
2021-03-24 20:37:53
这种对“Eloquent Javascript”注释的解释是落后的如果您真的只想检查未定义,则建议的代码将不起作用(它还将检测已定义的条件,但尚未确定任何值 [ienull])。空值。建议的代码“如果(东西==未定义)......”支票undefined和null(无设置值),也就是说,它的解释为:“如果((东西是未定义)OR(什么是空))...”什么作者的意思是,你往往是什么真正想要的是检查两个undefined和null。
2021-03-25 20:37:53
如果某物是未定义的全局变量, (something == undefined) 会引发 javascript 错误。
2021-03-28 20:37:53
if (something == undefined) 最好写成 if (something === undefined)
2021-04-04 20:37:53

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

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

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)您只想知道对象是否具有某些属性而不关心它的value。

'prop' in obj

笔记:

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

决战:obj.prop === undefinedvstypeof obj.prop == 'undefined'

优点obj.prop === undefined

  • 它有点短,看起来有点漂亮
  • 如果您拼写错误,JavaScript 引擎会给您一个错误 undefined

的缺点obj.prop === undefined

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

优点typeof obj.prop == 'undefined'

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

的缺点typeof obj.prop == 'undefined'

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

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

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

它不需要额外的文档,因为它在 EcmaScript 规范中,它也说这[[Enumerable]]是错误的 :-)
2021-03-21 20:37:53
@hlovdal:这对obj.prop === undefined.
2021-03-26 20:37:53
@Bergi 感谢您的评论。我已经更正了我的答案。在我的辩护中,我可以说目前(从 v.0.10.18 开始)官方 Node.js 文档没有提及undefined作为global. 同样,console.log(global);也不会将 undefinedfor (var key in global) { ... }显示global的成员但是测试就像显示相反。'undefined' in global
2021-03-27 20:37:53
关于Minuses of typeof obj.prop == 'undefined',这可以通过写作来避免typeof obj.prop == typeof undefined这也提供了非常好的对称性。
2021-03-29 20:37:53
当我们对问题标题检测未定义的属性”是真实的,而不是对第一句(“检查是否未定义...”)中的(不同且更简单的)问题if ('foo' in o是真实的时,您的回答是……您的答案确实是这里的第一个正确答案。几乎所有其他人都只是回答这句话。
2021-04-05 20:37:53