ChatGPT解决这个技术问题 Extra ChatGPT

变量 === 未定义与 typeof 变量 === “未定义”

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

全局变量:typeof 变量 === "undefined"

局部变量:变量 === 未定义

属性:object.prop === 未定义

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

我无法回答为什么 JQuery 会同时使用这两种方法的问题,但是 Javascript 确实有一些有趣的怪癖,这意味着这两种方法有细微的不同。大多数时候都应该没关系(即,如果您的代码是健全的),但仍然存在差异:请参阅此处了解文章 - wtfjs.com/2010/02/15/undefined-is-mutable
正如@Struppi 指出的那样,jQuery 的最外层函数有一个名为 undefined 的参数。在 jQuery 中,foo === undefined 正在检查 undefined 的本地副本而不是全局 (window.undefined),后者可能已被疯狂的代码修改。 undefined 是可变的这一事实绝对值得注意,我很高兴你做到了。 (+1)

L
Linus Kleen

对于未声明的变量,typeof foo 将返回字符串文字 "undefined",而身份检查 foo === undefined 将触发错误 “foo is not defined”

对于局部变量(您知道在某处声明),不会发生此类错误,因此需要进行身份检查。


@goreSplatter 你现在不能删除它。 :-) 很难选择,但问题的措辞方式,这个答案更合适。任何对 undefined 一般如何工作感兴趣的人(就像我一样)也应该看看其他答案,尤其是@Tim's。
我会添加引号 (typeof foo; // -> "undefined") 以强调它是一个字符串而不是原始值 undefined
L
Linus Kleen

我会坚持在任何地方使用 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 检查。


谢谢蒂姆。你关于性能的观点是有道理的。 jQuery 团队可能更关心对文件大小的影响。 foo === undefined 最小化后可能类似于 f===u,而 typeof foo === "undefined" 只能减少为 typeof f==="undefined"
您可以定义 var u = "undefined" 并将其缩减为 typeof f==u,这会改进但仍然更大。
好点,但我不确定 typeof 对未声明变量的安全性是否是一个优势。如果有什么让错别字更容易漏掉的话,我看不出你什么时候真正想要检查未声明变量的类型。
@Box9:我可以想象在一个库中使用它来检查另一个库的存在。
@jontro:那是不使用 JSLint 的原因之一。
t
t.niese

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

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

typeof variable 的结果不能。

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

15.1.1 全局对象的值属性 [...] 15.1.1.3 undefined undefined 的值是 undefined(见 8.1)。该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: 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")

无法在 ES5 中重新定义。
全局 undefined 属性不能在 ES5 中重新定义,但仍然可以使用局部变量进行遮蔽。 void 0 更短更安全。
我想说,如果你的代码重新定义了 undefined 那么你有比是否使用 typeof 更大的问题要处理。
S
SherylHohman

因为 undefined 并不总是被声明,而是 jQuery 在其主函数中声明了 undefined。所以他们在内部使用安全的 undefined 值,但在外部,他们使用 typeof 样式是安全的。


R
RiZKiT

variable === undefined的性能提升有兴趣的可以看看这里,不过好像只是chrome优化。

http://jsperf.com/type-of-undefined-vs-undefined/30

http://jsperf.com/type-of-undefined-vs-undefined


C
CodingYoshi

对于局部变量,使用 localVar === undefined 检查会起作用,因为它们必须是在局部范围内的某个地方定义的,否则它们不会被视为局部变量。

对于不是本地且未在任何地方定义的变量,检查 someVar === undefined 将抛出异常:Uncaught ReferenceError: j is not defined

这是一些代码,可以澄清我上面所说的内容。请注意内联注释以获得进一步的清晰度。

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 ==>


W
Willem van der Veen

概括:

在全局范围内,如果变量未声明或值为 undefined,我们实际上希望返回 true:

变量 globalVar1; // 此变量已声明,但未定义,因此值为 undefined console.log(globalVar1 === undefined); // 这个变量没有声明,因此会抛出一个referenceError console.log(globalVar2 === undefined);

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

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

这是因为 typeof 运算符在未声明变量或当前持有值 undefined 时返回字符串 undefined,这正是我们想要的。

使用局部变量我们没有这个问题,因为我们事先知道这个变量会存在。如果变量存在,我们可以简单地查看相应的函数。

对于对象属性,我们没有这个问题,因为当我们尝试查找不存在的对象属性时,我们也会得到值 undefined

变量 obj = {}; console.log(obj.myProp === undefined);


C
CDspace

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


这些与您键入的内容不同。我认为您在第二部分的意思是 undefined,而不是 'undefined'