哪种检查变量是否已初始化的方法更好/正确?(假设变量可以保存任何内容(字符串、int、对象、函数等))
if (elem) { // or !elem
or
if (typeof elem !== 'undefined') {
or
if (elem != null) {
哪种检查变量是否已初始化的方法更好/正确?(假设变量可以保存任何内容(字符串、int、对象、函数等))
if (elem) { // or !elem
or
if (typeof elem !== 'undefined') {
or
if (elem != null) {
当前回答
我的首选是typeof(elem)!='未定义'&&elem!=无效的
无论您选择什么,请考虑将检查放入这样的函数中
function existy (x) {
return typeof (x) != 'undefined' && x != null;
}
如果您不知道变量已声明,请继续使用typeof(x)!='未定义'&&x!=无效的
如果您知道变量已声明但可能不存在,可以使用
existy(elem) && doSomething(elem);
您正在检查的变量有时可能是嵌套属性。您可以使用prop | |{}来检查问题属性的存在性:
var exists = ((((existy(myObj).prop1||{}).prop2||{}).prop3||{})[1]||{}).prop4;
在每个属性之后,使用(…“| |{}”).nexPro,以便丢失的属性不会引发错误。
或者,您可以使用existy,如existy(o)&&exist(o.p)&&existiny(o.p.q)&&doSomething(o.p.q)
其他回答
我更喜欢这种方法,因为它的准确性和简洁性:
变量x如果(x===无效0){console.log(“x未定义”)}其他{console.log(“x已定义”)}
正如在其他评论和回答中提到的,undefined不能保证是undefineed。因为它不是关键字,所以可以在全局范围以外的范围中将其重新定义为变量。这里有一个小例子可以说明这种细微差别:
var undefined='bar'console.log(`在全局范围内:${undefined}`)函数foo(){var undefined=“已定义”变量x如果(x===未定义){console.log(`x===undefined`)}其他{console.log(`x!==undefined`)}如果(x===无效0){console.log(`x===void 0`)}其他{console.log(`x!==void 0`)}}foo()
请参阅void以了解兼容性(IE5支持!?!!哇!)。
这取决于情况。如果您正在检查代码之外可能或可能尚未全局定义的内容(例如jQuery),您需要:
if (typeof(jQuery) != "undefined")
(这里不需要严格相等,typeof总是返回字符串。)但是,如果函数的参数可能已传递,也可能未传递,则它们将始终被定义,但如果忽略,则为null。
function sayHello(name) {
if (name) return "Hello, " + name;
else return "Hello unknown person";
}
sayHello(); // => "Hello unknown person"
如何检查变量是否存在
这是一个非常可靠的解决方案,用于测试变量是否存在并已初始化:
var setOrNot = typeof variable !== typeof undefined;
它最常用于与三元运算符结合使用,以在某个变量尚未初始化的情况下设置默认值:
var dark = typeof darkColor !== typeof undefined ? darkColor : "black";
封装问题
不幸的是,您不能简单地将检查封装在函数中。
你可能会想到这样做:
function isset(variable) {
return typeof variable !== typeof undefined;
}
然而,如果您正在调用例如isset(foo),并且尚未定义变量foo,这将产生引用错误,因为您无法将不存在的变量传递给函数:
未捕获引用错误:未定义foo
测试函数参数是否未定义
虽然我们的isset函数不能用于测试变量是否存在(原因如上所述),但它确实允许我们测试函数的参数是否未定义:
var a = '5';
var test = function(x, y) {
console.log(isset(x));
console.log(isset(y));
};
test(a);
// OUTPUT :
// ------------
// TRUE
// FALSE
即使没有将y的值传递给函数测试,我们的isset函数在这种情况下也能很好地工作,因为在函数测试中y是一个未定义的值。
在JavaScript中,可以定义变量,但保持值未定义,因此最常见的答案在技术上不正确,而是执行以下操作:
if (typeof v === "undefined") {
// no variable "v" is defined in the current scope
// *or* some variable v exists and has been assigned the value undefined
} else {
// some variable (global or local) "v" is defined in the current scope
// *and* it contains a value other than undefined
}
这可能足以满足你的目的。以下测试具有更简单的语义,这使得准确描述代码的行为并自己理解它变得更容易(如果您关心这些事情):
if ("v" in window) {
// global variable v is defined
} else {
// global variable v is not defined
}
当然,这假设您在浏览器中运行(其中window是全局对象的名称)。但如果你在摆弄这样的全局变量,你很可能是在浏览器中。主观上,在window中使用“name”在风格上与使用window.name来引用全局变量一致。将全局变量作为窗口的财产而不是变量进行访问,可以最大限度地减少代码中引用的未声明变量的数量(为了linting的好处),并避免全局变量被局部变量遮蔽的可能性。此外,如果全局对象使您的皮肤爬行,您可能会觉得仅用这根相对较长的棍子触摸它们更舒服。
检查window.hasOwnProperty(“varname”)
一种替代过多类型答案的方法;
用var varname=value声明的全局变量;全局范围内的语句
可以作为窗口对象的财产访问。
因此,hasOwnProperty()方法
返回一个布尔值,指示对象是否将指定的属性作为自己的属性(而不是继承它)可用于确定
“varname”的var已全局声明,即是窗口的属性。
//因此,在全球范围内建立了窗口的财产var foo=“whatever”,//stringbar=false,//bool巴兹;//未定义//window.qux不存在console.log([window.hasOwnProperty(“foo”),//truewindow.hasOwnProperty(“bar”),//truewindow.hasOwnProperty(“baz”),//truewindow.hasOwnProperty(“qux”)//false] );
hasOwnProperty()的优点在于,在调用它时,我们没有使用一个尚未声明的变量,这当然是问题的一半。
虽然不总是完美或理想的解决方案,但在某些情况下,这只是工作!
笔记
当使用var定义变量时,上述情况是正确的,而不是let which:
声明一个块作用域局部变量,可选地将其初始化为一个值。与var关键字不同,var关键字全局定义变量,或局部定义整个函数,而不考虑块范围。在程序和函数的顶层,let与var不同,它不会在全局对象上创建属性。
为了完整性:根据定义,常量实际上不是可变的(尽管它们的内容可以是可变的);更相关的是:
与var变量不同,全局常量不会成为窗口对象的财产。常量的初始值设定项是必需的;也就是说,必须在声明它的同一语句中指定它的值。常量的值不能通过重新分配来更改,也不能重新声明。const声明创建对值的只读引用。这并不意味着它所持有的值是不可变的,只是变量标识符不能被重新分配。
由于let变量或常量永远不是继承了hasOwnProperty()方法的任何对象的财产,因此不能使用它来检查它们是否存在。
关于hasOwnProperty()的可用性和使用:
object派生的每个对象都继承hasOwnProperty()方法。[…]与in运算符不同,此方法不检查对象的原型链。