检查JavaScript中的对象属性是否未定义的最佳方法是什么?
使用:
if (typeof something === "undefined") { alert("something is undefined"); }
如果一个具有某些属性的对象变量可以使用相同的东西:
if (typeof my_obj.someproperties === "undefined"){ console.log('the property is not available...'); // print into console }
我相信这个话题有很多不正确的答案.与普遍看法相反,"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未声明的情况下会引发错误.
尽管在这里被许多其他答案强烈推荐,但这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) { … }
,称为bar()
)将失败.这根本不是真的 - 没有显式初始化的变量和未给定值的参数总是变成undefined
,并且始终在范围内.
这undefined
可以被覆盖.这还有更多.undefined
不是JavaScript中的关键字.相反,它是具有Undefined值的全局对象上的属性.但是,从ES5开始,此属性是只读且不可配置的.没有现代化的浏览器undefined
可以更改房产,截至2017年,情况已经很长时间了.缺乏严格模式也不会影响其undefined
行为 - 它只会使声明undefined = 5
无所事事而不是投掷.但是,由于它不是关键字,您可以使用名称声明变量undefined
,并且可以更改这些变量,从而形成这种曾经常见的模式:
(function (undefined) { // … })()
比使用全局更危险undefined
.如果您必须与ES3兼容,请替换undefined
为void 0
- 不要诉诸typeof
.(void
一直是一元运算符,计算任何操作数的Undefined值.)
关于变量如何工作,是时候解决实际问题了:对象属性.没有理由使用typeof
对象属性.关于特征检测的早期例外在这里不适用 - typeof
仅对变量有特殊行为,而引用对象属性的表达式不是变量.
这个:
if (typeof foo.bar === 'undefined') { ? }
是始终完全等同于this³:
if (foo.bar === undefined) { ? }
并考虑上面的建议,以避免让读者混淆你为什么使用typeof
,因为它最有意义的===
用于检查相等性,因为它可以重构为稍后检查变量的值,因为它只是简单的看起来更好,你应该总是=== undefined
在这里使用³.
在涉及对象属性时需要考虑的其他事项是你是否真的想要检查它undefined
.给定的属性名称可以在对象上不存在(undefined
在读取时产生值),在对象本身上显示值undefined
,在对象的原型上显示值undefined
,或者存在于具有非undefined
值的任何一个上.'key' in obj
将告诉您一个键是否在对象的原型链上的任何位置,Object.prototype.hasOwnProperty.call(obj, 'key')
并将告诉您它是否直接在该对象上.我不会在这个关于原型和使用对象作为字符串键映射的答案中详细说明,因为它主要是为了对抗其他答案中的所有不良建议,而不管原始问题的可能解释.在MDN上阅读对象原型以获取更多信息!
¹异常选择示例变量名称?这是来自Firefox的NoScript扩展的真正死代码.
²不要以为不知道一般情况下不知道范围是什么.滥用动态范围引起的奖励漏洞:Project Zero1225³
再次假设ES5 +环境并且undefined
指undefined
的是全局对象的属性.void 0
否则替代.
在JavaScript中有null并且未定义.它们有不同的含义.
undefined表示尚未定义变量值; 不知道它的价值是什么.
null表示定义变量值并设置为null(没有值).
Marijn Haverbeke在他的免费在线书" Eloquent JavaScript "(强调我的)中说:
还有一个类似的值null,其含义是'此值已定义,但它没有值'.undefined和null之间的意义差异主要是学术性的,通常不是很有趣.在实际程序中,通常需要检查某些东西是否"有价值".在这些情况下,可以使用表达式== undefined,因为即使它们不是完全相同的值,null == undefined也会产生true.
所以,我想检查某些内容是否未定义的最佳方法是:
if (something == undefined)
希望这可以帮助!
编辑:为了响应您的编辑,对象属性应该以相同的方式工作.
var person = { name: "John", age: 28, sex: "male" }; alert(person.name); // "John" alert(person.fakeVariable); // 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
我们可以清楚地看到它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第1版以来一直受到支持,因此ECMAScript 5 只读它.因此,在现代浏览器中,它不能被重新定义为真实,因为许多作者喜欢用我们来吓唬我们,但对于旧浏览器来说这仍然是正确的.
obj.prop === undefined
vstypeof obj.prop == 'undefined'
优点obj.prop === undefined
:
它有点短,看起来更漂亮
如果拼写错误,JavaScript引擎会给您一个错误 undefined
缺点obj.prop === undefined
:
undefined
可以在旧浏览器中覆盖
优点typeof obj.prop == 'undefined'
:
它真的很普遍!它适用于新旧浏览器.
缺点typeof obj.prop == 'undefined'
:
'undefned'
(拼写错误)这里只是一个字符串常量,所以如果你像我刚才拼错了那么JavaScript引擎无法帮助你.
Node.js的支持全局变量undefined
如global.undefined
(它也可以在没有所述"全局"前缀使用).我不知道服务器端JavaScript的其他实现.
问题归结为三种情况:
该对象具有该属性,而其值不是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); }
但正如已经提到的那样,它们并不完全相同(但对我的需求来说已经足够了).
if ( typeof( something ) == "undefined")
这对我有用,而其他人没有.
我不知道在哪里使用的起源===
与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
从相关问题中删除我的答案如何在JavaScript中检查"未定义"?
具体到这个问题,请参阅测试用例someObject.
.
一些场景说明了各种答案的结果:http: //jsfiddle.net/drzaus/UVjM4/
(请注意,在作用域包装器中使用var
for 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
如果你这样做
if (myvar == undefined ) { alert('var does not exists or is not initialized'); }
当变量myvar
不存在时它将失败,因为myvar未定义,因此脚本被破坏且测试无效.
由于窗口对象在函数外部具有全局范围(默认对象),因此声明将"附加"到窗口对象.
例如:
var myvar = 'test';
全局变量myvar与window.myvar或window ['myvar']相同
为避免在存在全局变量时测试错误,最好使用:
if(window.myvar == undefined ) { alert('var does not exists or is not initialized'); }
变量确实存在的问题无关紧要,其值不正确.否则,使用undefined初始化变量是愚蠢的,最好使用值false来初始化.当您知道所声明的所有变量都使用false初始化时,您只需检查其类型或依赖!window.myvar
检查它是否具有正确/有效的值.因此,即使当变量未被定义!window.myvar
是相同的myvar = undefined
或myvar = false
或myvar = 0
.
当您需要特定类型时,请测试变量的类型.为了加快测试条件,您最好:
if( !window.myvar || typeof window.myvar != 'string' ) { alert('var does not exists or is not type of string'); }
当第一个和简单条件为真时,解释器会跳过下一个测试.
最好使用变量的实例/对象来检查它是否具有有效值.它更稳定,是一种更好的编程方式.
(y)的
我没有看到(希望我没有错过)任何人在物业前检查物体.所以,这是最短且最有效的(尽管不一定最清楚):
if (obj && obj.prop) { // Do something; }
如果obj或obj.prop未定义,null或"falsy",则if语句将不执行代码块.这通常是大多数代码块语句(在JavaScript中)中所需的行为.
在JavaScript中探索Null和Undefined的深渊文章我读到像Underscore.js这样的框架使用这个函数:
function isUndefined(obj){ return obj === void 0; }
只是在JavaScript中没有定义任何东西,未定义,如果它是Object/Array中的属性或仅仅是一个简单的变量也无关紧要......
JavaScript typeof
使得检测未定义的变量非常容易.
只需检查是否typeof whatever === 'undefined'
会返回布尔值.
这就是isUndefined()
AngularJs v.1x中着名函数的编写方式:
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
在代码中使用,但如果你反复使用它,创建一个像我分享的角度样本一样的函数,并继续重用遵循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框架如下划线也有类似的定义检查,但我建议你使用,typeof
如果你已经没有使用任何框架.
我还从MDN添加了这一部分,其中包含有关typeof,undefined和void(0)的有用信息.
严格的相等和未定义
您可以使用undefined和严格的相等和不等运算符来确定变量是否具有值.在以下代码中,未定义变量x,if语句的计算结果为true.
var x; if (x === undefined) { // these statements execute } else { // these statements do not execute }
注意:此处必须使用严格相等运算符而不是标准相等运算符,因为x == undefined也会检查x是否为null,而严格相等则不会.null不等于undefined.有关详细信息,请参见比较
Typeof运算符和undefined
或者,可以使用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运算符和undefined
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`) }
更多> 这里
你很可能想要的if (window.x)
.即使x尚未声明(var x;
),此检查也是安全的- 浏览器不会抛出错误.
if (window.history) { history.call_some_function(); }
window是一个将所有全局变量保存为其成员的对象,尝试访问不存在的成员是合法的.如果x尚未声明或尚未设置,则window.x
返回undefined.当if()计算它时,undefined会导致false.
"propertyName" in obj //-> true | false
通过阅读,我很惊讶我没有看到这一点.我找到了多种适用于此的算法.
永不定义如果从未定义对象的值,true
则如果将其定义为null
或,则将阻止返回undefined
.如果您希望为设置为的值返回true,这将非常有用undefined
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");定义为假值,未定义,null或从未定义.
通常,人们问我一个算法来判断一个值是否是假的undefined
,或者null
.以下作品.
if(obj.prop == false || obj.prop === null || obj.prop === undefined) { console.log("The value is falsy, null, or undefined"); }
您可以使用以下代码获取所有未定义的数组.
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链接
与void 0
简洁相比较.
if (foo !== void 0)
它不像那样冗长 if (typeof foo !== 'undefined')
解决方案不正确.在JavaScript中,
null == undefined
将返回true,因为它们都被"转换"为布尔值并且为false.正确的方法是检查
if (something === undefined)
这是身份运营商......
这是我的情况:
我正在使用REST调用的结果.结果应该从JSON解析为JavaScript对象.
我需要保护一个错误.如果用户指定args错误,其余调用的args是不正确的,则其余的调用基本上是空的.
虽然使用这篇文章来帮助我防范这个,但我尝试了这个.
if( typeof restResult.data[0] === "undefined" ) { throw "Some error"; }
对于我的情况,如果restResult.data [0] ==="对象",那么我可以安全地开始检查其余的成员.如果未定义,则抛出上述错误.
我所说的是,就我的情况而言,本文上面的所有建议都不起作用.我不是说我是对的,每个人都错了.我根本不是JavaScript大师,但希望这会对某人有所帮助.
如果已定义属性,则可以将定义的属性分配给新变量,如果未定义,则将其作为回退分配给它.
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
所有答案都不完整.这是知道某个属性"定义为未定义"的正确方法:
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
太糟糕了,这是正确的答案被埋在错误的答案> _ <
所以,对于经过的人,我会免费给你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
通过注释,对于那些想要检查它们的人来说,它是未定义的或其值为null:
//Just in JavaScript var s; // Undefined if (typeof s == "undefined" || s === null){ alert('either it is undefined or value is null') }
如果您使用的是jQuery Library,那么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;
如果您使用的是Angular:
angular.isUndefined(obj) angular.isUndefined(obj.prop)
Underscore.js:
_.isUndefined(obj) _.isUndefined(obj.prop)
我if (this.variable)
用来测试它是否已定义.简单if (variable)
,上面推荐,对我来说失败了.事实证明,它仅在变量是某个对象的字段时起作用,obj.someField
以检查它是否在字典中定义.但我们可以使用this
或window
作为字典对象,因为任何变量都是当前窗口中的字段,据我所知.因此这是一个测试
if (this.abc) alert("defined"); else alert("undefined");
abc = "abc";
if (this.abc) alert("defined"); else alert("undefined");
对于那些期望得到怪异答案的人,我在这里提供了三种方法:
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);