如何检查JavaScript中的对象属性是否未定义?


当前回答

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

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

其他回答

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

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

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

实际上,这可能意味着两件截然不同的事情!首先,它可以表示对象中从未定义过的属性,其次,它可以指具有未定义值的属性。让我们看一下这段代码:

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

我们可以清楚地看到,obj.prop==“undefined”和obj.prop==undefineed的类型是等价的,它们不能区分这些不同的情况。obj中的“prop”可以检测属性根本没有定义并且没有注意可能未定义的属性值的情况。

那该怎么办?

1) 您想知道一个属性是由第一个含义还是第二个含义定义的(最典型的情况)。

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

2) 您只想知道对象是否具有某些属性,而不关心其值。

'prop' in obj

笔记:

不能同时检查对象及其属性。例如,此x.a==未定义或此类型的x.a=='未定义'引发ReferenceError:如果未定义x,则未定义x。变量undefined是一个全局变量(所以实际上它在浏览器中是window.unded)。自ECMAScript第1版以来,它一直受到支持,自ECMASript 5以来,它是只读的。因此,在现代浏览器中,它不能被重新定义为真实,因为许多作者喜欢用它来吓唬我们,但这对于旧浏览器来说仍然是真实的。

最后一战:obj.prop==未定义vs obj.prop类型==“未定义”

obj.prop的加号==未定义:

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

obj.prop的最小值==未定义:

在旧浏览器中可以重写undefined

obj.prop类型的加号==“undefined”:

它真的很普遍!它可以在新旧浏览器中使用。

obj.prop类型的最小值==“undefined”:

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

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

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

简单地说,JavaScript中没有定义的任何东西都是未定义的,无论它是Object/Array中的属性还是只是一个简单的变量。。。

JavaScript具有类型of,因此很容易检测未定义的变量。

只需检查typeof whatever==“undefined”,就会返回布尔值。

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

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

因此,当您看到函数接收到一个值时,如果定义了该值,它将返回false,否则对于未定义的值,返回true。

让我们看看传递值时会得到什么结果,包括如下所示的对象财产,这是我们拥有的变量列表:

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

我们如下所示进行检查,您可以在他们面前看到结果作为评论:

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

正如您所看到的,我们可以在代码中使用类似的东西来检查任何情况,正如前面所提到的,您可以在您的代码中简单地使用typeof,但是如果您反复使用它,请创建一个像我共享的angular sample这样的函数,并将其作为以下DRY代码模式继续重用。

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

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

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

如此简单,您可以像下面这样包装在if语句中:

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

也等于在Angular 1.x中定义的。。。

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

其他javascript框架(如下划线)也有类似的定义检查,但如果您尚未使用任何框架,我建议您使用typeof。

我还从MDN中添加了这一部分,它提供了关于typeof、undefined和void(0)的有用信息。

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

var x;
if (x === undefined) {
   // these statements execute
}
else {
   // these statements do not execute
}

注意:严格等式运算符而不是标准等式这里必须使用运算符,因为x==undefined还检查x为空,而严格相等不为空。null不等于未定义。有关详细信息,请参见比较运算符。


运算符类型和未定义或者,可以使用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`)
}

更多>此处

使用动态变量的版本你知道吗?

var boo='Ala';函数检查(){if(this['fo']){console.log('o is here');}其他{console.log('没有foo');}如果(这个['bo']){console.log('boo在这里');}其他{console.log('没有boo');}}check();

这里的许多答案都强烈推荐typeof,但typeof是一个糟糕的选择。它不应用于检查变量是否具有未定义的值,因为它充当了未定义值和变量是否存在的组合检查。在绝大多数情况下,您知道变量何时存在,如果您在变量名称或字符串文字“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) {
    ⋮
}

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

读取“未初始化”变量(varfoo)或参数(函数栏(foo){…},称为bar())将失败。这根本不是真的——没有显式初始化的变量和没有给定值的参数总是未定义,并且总是在范围内。可以覆盖未定义的。的确,undefined不是关键字,但它是只读的,不可配置。尽管有其他内置程序的非关键字状态(Object、Math、NaN…),但您可能无法避免它们,而且实用代码通常不是在主动恶意环境中编写的,因此这不是担心未定义的好理由。(但如果您正在编写代码生成器,请随意使用void 0。)

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

这:

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

始终完全等于此³:

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

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

当涉及到对象财产时,需要考虑的另一件事是您是否真的想检查未定义的属性。给定的属性名称可以在对象上不存在(读取时产生未定义的值),可以在对象本身上出现,但值未定义,可以在该对象的原型上出现,值未定义或出现在其中一个值未定义的对象上obj中的“key”将告诉您键是否位于对象原型链上的任何位置,而object.protype.hasOwnProperty.call(obj,“key”)将告诉您它是否直接位于对象上。不过,我不会在这个答案中详细讨论原型和使用对象作为字符串键映射,因为它主要是为了应对其他答案中的所有坏建议,而不管对原始问题的可能解释。阅读MDN上的对象原型了解更多信息!

¹不寻常的变量名称示例选择?这是Firefox的NoScript扩展中真正的死代码。²但是,不要认为不知道范围内的内容是可以的。滥用动态范围导致的奖金漏洞:项目零1225再次假设ES5+环境,undefined指的是全局对象的未定义属性。