jquery 变量===未定义与变量类型===“未定义”

brvekthn  于 2022-11-03  发布在  jQuery
关注(0)|答案(9)|浏览(320)

jQuery Core Style Guidelines建议了两种不同的方法来检查变量是否被定义。

  • 全局变量:variable === undefined
  • 局部变量:variable === undefined
  • 属性:object.prop === undefined

为什么jQuery对全局变量使用一种方法,而对局部变量和属性使用另一种方法?

tkqqtvp1

tkqqtvp11#

对于未声明的变量,typeof foo将返回字符串文字"undefined",而标识检查foo === undefined将触发错误 “foo is not defined”
对于局部变量(您 * 知道 * 在某处声明),不会发生这样的错误,因此需要进行标识检查。

8fq7wneg

8fq7wneg2#

我会坚持在任何地方使用typeof foo === "undefined",这永远不会出错。
我想jQuery推荐这两种不同方法的原因是它们在jQuery代码所在的函数中定义了自己的undefined变量,因此在该函数中undefined是安全的,不会受到外部的篡改。我还可以想象,有人在某处对这两种不同的方法进行了基准测试,发现foo === undefined更快,因此决定采用这一方法。**[更新:如注解中所述,与undefined的比较也略短,这可能是一个考虑因素。]**然而,在实际情况下的增益将是完全微不足道的:这一检查将永远不会成为任何类型的瓶颈,而您所失去的将是巨大的:评估用于比较的主机对象的属性可能抛出错误,而typeof检查永远不会抛出错误。
例如,在IE中使用以下代码来解析XML:

var x = new ActiveXObject("Microsoft.XMLDOM");

要安全地检查它是否具有loadXML方法:

typeof x.loadXML === "undefined"; // Returns false

另一方面:

x.loadXML === undefined; // Throws an error

更新

typeof检查的另一个优点是,它还可以处理未声明的变量,而foo === undefined检查则不能,实际上它会抛出一个ReferenceError。感谢@LinusKleen提醒我。例如:

typeof someUndeclaredVariable; // "undefined"
someUndeclaredVariable === undefined; // throws a ReferenceError

底线:请始终使用typeof检查。

r8xiu3jd

r8xiu3jd3#

使用typeof-variant的另一个原因是:可以重新定义undefined

undefined = "foo";
var variable = "foo";
if (variable === undefined)
  console.log("eh, what?!");

typeof variable的结果不能。

更新:请注意,在ES 5中情况并非如此,全局undefined是不可配置、不可写的属性:

15.1.1全局对象的值属性
[...]
15.1.1.3 未定义
undefined的值未定义(请参见8.1)。
{ 可写:false,可枚举:false,可配置:错误}。
但它仍然可以被局部变量遮蔽:

(function() {
  var undefined = "foo";
  var variable = "foo";
  if (variable === undefined)
    console.log("eh, what?!");  
})()

或参数:

(function(undefined) {
  var variable = "foo";
  if (variable === undefined)
    console.log("eh, what?!");  
})("foo")
uidvcgyl

uidvcgyl4#

因为undefined并不总是声明的,但是jQuery在它的main函数中声明了undefined,所以它们在内部使用安全的undefined值,但是在外部,它们使用typeof样式来保证安全。

gzszwxb4

gzszwxb45#

谁对variable === undefined的性能增益感兴趣,可能会在这里看一看,但它似乎只是一个chrome优化。

8hhllhi2

8hhllhi26#

对于局部变量,使用localVar === undefined进行检查将有效,因为它们必须已在局部范围内的某个位置定义,否则将不被视为局部变量。
对于非局部变量和未在任何位置定义的变量,检查someVar === undefined将抛出异常:* 未捕获的引用错误:j未定义 *
这里有一些代码,将澄清我在上面说的话。* 请注意进一步澄清内联注解 *。

function f (x) {
    if (x === undefined) console.log('x is undefined [x === undefined].');
    else console.log('x is not undefined [x === undefined.]');

    if (typeof(x) === 'undefined') console.log('x is undefined [typeof(x) === \'undefined\'].');
    else console.log('x is not undefined [typeof(x) === \'undefined\'].');

    // This will throw exception because what the hell is j? It is nowhere to be found.
    try
    {
        if (j === undefined) console.log('j is undefined [j === undefined].');
        else console.log('j is not undefined [j === undefined].');
    }
    catch(e){console.log('Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.');}

    // However this will not throw exception
    if (typeof j === 'undefined') console.log('j is undefined (typeof(x) === \'undefined\'). We can use this check even though j is nowhere to be found in our source code and it will not throw.');
    else console.log('j is not undefined [typeof(x) === \'undefined\'].');
};

如果我们这样调用上面的代码:

f();

输出结果如下:

x is undefined [x === undefined].
x is undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.

如果我们像这样调用上面的代码(实际上是任意值):

f(null); 
f(1);

输出将为:

x is not undefined [x === undefined].
x is not undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.

当你这样做检查时:typeof x === 'undefined',您实际上是在问:* 请检查变量x是否在源代码中的某个地方存在(已定义)。*(或多或少)。如果您了解C#或Java,则永远不会执行此类检查,因为如果它不存在,则无法编译。
<== Fiddle Me ==>

bwleehnv

bwleehnv7#

总结:

在全局作用域中,如果变量没有声明或者其值为undefined,我们实际上希望返回true:

var globalVar1;

// This variable is declared, but not defined and thus has the value undefined
console.log(globalVar1 === undefined);

// This variable is not declared and thus will throw a referenceError
console.log(globalVar2 === undefined);

因为在全局范围内,我们不能100%确定变量是否被声明,这可能会给予我们一个referenceError。当我们在未知变量上使用typeof运算符时,如果变量没有被声明,我们就不会遇到这个问题:

var globalVar1;

console.log(typeof globalVar1 === 'undefined');
console.log(typeof globalVar2 === 'undefined');

这是由于typeof运算符返回字符串undefined,而变量未声明或当前的值为undefined,这正是我们想要的。

  • 使用局部变量就不会有这样的问题,因为我们事先知道这个变量是存在的,我们可以简单地在相应的函数中查看变量是否存在。
  • 对于对象属性,我们不会遇到此问题,因为当我们尝试查找不存在的对象属性时,我们也会得到值undefined
var obj = {};

console.log(obj.myProp === undefined);
uyhoqukh

uyhoqukh8#

JavaScript中“未定义”的含义

这个问题与变量的局部与全局作用域、jQuery决策等无关。undefined有两个不同的表达式,以及三种不同的用法,如下所示:

1.**“typeof”和“未定义”**类型:没有声明和不存在的变量不会被赋值,但其“类型”为undefined。如果您访问一个甚至不存在的变量,更不用说声明或初始化了,那么访问它时将生成一个引用错误。即使在测试undefined的基元默认值时也是如此,该基元默认值在赋值之前一直被赋给声明的变量。因此,检查“typeof”在此情况下,可防止此错误,如下所示:

// In this first test, the variable "myVariable1" does not exist yet so creates
    // an error if we try and check if its assigned the default value of undefined!
    if (myVariable1 === undefined) alert(true);// REFERENCE ERROR!

    // Here we can elegantly catch the "undefined" type 
    // of the missing variable and stop the REFERENCE ERROR using "typeof".
    if (typeof myVariable1 === "undefined") alert(true);// true

    // Here we have declared the missing variable and notice its 
    // still an "undefined" type until initialized with a value.
    let myVariable1;
    if (typeof myVariable1 === "undefined") alert(true);// true

    // Lastly, after we assign a value, the type is no longer 
    // "undefined" so returns false.
    myVariable1 = 'hello';
    if (typeof myVariable1 === "undefined") alert(true);// false

JavaScript中所有被访问但未声明的对象和类型将默认为“undefined”类型。因此,这里的课程是首先尝试检查typeof,以防止丢失变量错误!
1.undefined基元值:在JavaScript中,所有尚未赋值的已声明变量都被赋值为undefinedprimitve。如果您已经声明了一个变量,但尚未初始化它,则会将其赋值为默认的 * primitve * 类型undefined。这与“undefined”类型不同。undefined的基元值是一个 reserved 值,但可以更改。但这并不是这里所要求的。请注意,这里只捕获所有已声明但未初始化的变量:

let myVariable3;
    if (myVariable3 === undefined) alert(true);// true

    let myVariable4 = 'hello';
    if (myVariable4 === undefined) alert(true);// false

1.对象和undefined基元:最后,Object属性的行为与JavaScript中的变量不一样。Object属性在缺失时不会变成未定义的类型,而只是像上面未声明的变量一样被赋以 primitiveundefined。因此,它们的行为类似于#2:

let myObject = {};
    if (myObject.myProperty === undefined) alert(true);// true

最佳实践

最后......这是一个很好的理由,总是检查所有JavaScript代码中变量的“undefined”类型和undefinedprimitive 值。大多数人会说,你很少需要这两个。可能有一天,一个丢失的变量在一个不存在的库中被访问,并创建一个讨厌的JavaScript引用错误!所以我总是做这个检查,并按照这个顺序,停止JavaScript中的所有错误:

if (typeof myVariable !== "undefined" && myVariable !== undefined) {
    // do something safe with myVariable!
}
mpbci0fu

mpbci0fu9#

在节点v6.9.1上,typeof a === 'undefined'a === 'undefined'快大约2倍。

相关问题