typeof !== "未定义" vs. != null
Posted
技术标签:
【中文标题】typeof !== "未定义" vs. != null【英文标题】:typeof !== "undefined" vs. != null 【发布时间】:2011-02-11 18:50:28 【问题描述】:我经常看到 javascript 代码以这种方式检查未定义的参数等:
if (typeof input !== "undefined")
// do stuff
这似乎有点浪费,因为它涉及类型查找和字符串比较,更不用说它的冗长了。之所以需要它,是因为 undefined
可以重命名。
我的问题是: 该代码比这种方法更好:
if (null != input)
// do stuff
据我所知,您无法重新定义null
,因此它不会意外中断。而且,由于 !=
运算符的类型强制,这会检查 undefined
和 null
... 这通常正是您想要的(例如,对于可选函数参数)。
然而这种形式似乎并不普遍,它甚至会导致 JSLint 对你大喊大叫,因为你使用了邪恶的 !=
运算符。
为什么这被认为是不好的风格?
【问题讨论】:
@Marcel,没有真正的区别,但这样做有两个原因。一,对于某些人来说,阅读起来更清晰。第二个原因是它可以防止意外覆盖变量。你有没有这样做过:if( foo = "value" ) 打算进行比较时。如果您养成在赋值/比较运算符中反转变量的习惯,那么您将不会遇到这个问题。 对于某些人(包括我)来说,这实际上更难以阅读。此外,大多数 IDE 会警告您意外分配。但是如果比较变量很长,我仍然使用这种形式。 YMMV。 @MarcelKorpel 这被称为“尤达条件”:umumble.com/blogs/Programming/321 更难阅读。一个人不会说“瓶子不是空的”。if (null != input)
对说英语的人来说只是“尤达说话”(我是....恕我直言。
【参考方案1】:
typeof
更安全,因为它允许标识符之前从未被声明过:
if(typeof neverDeclared === "undefined") // no errors
if(neverDeclared === null) // throws ReferenceError: neverDeclared is not defined
【讨论】:
if ((typeof neverDeclared !== "undefined") && (neverDeclared !== null)) return true; 否则 返回假; 在与 null/undefined 进行比较时使用 ===。 @MyGGaN 仅在您想区分两者时使用。在许多情况下,==
会更好,因为它同时测试 null 和 undefined。
我找不到 typeof somevar == 'undefined' 和 typeof somevar === 'undefined' 之间的任何区别,因为 typeof 总是返回字符串。对于 null,它将返回“对象”。还是我错了?
我相信@TomTom 的评论是问题的症结所在——我不明白为什么在比较一个已知类型为字符串。【参考方案2】:
如果声明变量(使用var
关键字,作为函数参数,或作为全局变量),我认为最好的方法是:
if (my_variable === undefined)
jQuery 做到了,所以对我来说已经足够了 :-)
否则,您将不得不使用typeof
来避免ReferenceError
。
如果你希望 undefined 被重新定义,你可以像这样包装你的代码:
(function(undefined)
// undefined is now what it's supposed to be
)();
或者通过void
操作符获取:
const undefined = void 0;
// also safe
【讨论】:
如果 undefined 已经被定义了,那么你不会通过一个名为 undefined 的参数将它传递给你的匿名函数,什么都不做吗? @Anthony DiSanti:不,undefined
是函数参数的名称,而不是它的值。什么都没有传递给函数,这意味着第一个参数的值是未定义的。
我错了,感谢您的跟进。我已取消投票,对此感到抱歉。
为什么要编写一个异常来处理另一个开发人员声明的未定义,而您可以正确地开始呢? jQuery 包装了您在函数中显示的初始匿名函数,以确保未定义未定义并减小缩小的大小。简单地说,如果这样做会产生意想不到的结果,为什么要冒险进行惰性编程以避免打字(typeof variable === 'undefined')。如果我们想要 (typeof variable === 'object') 我们应该提供一个默认变量,它也是一个对象,以便我们可以这样做 (variable === object)?【参考方案3】:
好方法:
if(typeof neverDeclared == "undefined") //no errors
但最好看的方法是通过以下方式检查:
if(typeof neverDeclared === typeof undefined) //also no errors and no strings
【讨论】:
var undefined = function(); if( typeof neverDeclared === typeof undefined ); neverDecalred != '功能'; jsfiddle.net/hbPZ5 return typeof var;返回一个字符串。没有错误或字符串,但不会总是给出预期的结果。授予的开发人员不应声明 undefined,但有些框架和库可以这样做。 我主要使用if (typeof neverDeclared === typeof undefined)
但 Lint 会引发错误。 “本应是一个字符串,但看到的是‘typeof’。”您将如何解决此错误?我们是否应该服从 Lint 的要求并改用“好方法”?
@fyrye 你知道有哪些 JavaScript 库/框架实际上会改变 undefined 吗?我知道这是可能的;但我想找一个常见的例子,“在这里你可能会遇到这只讨厌的角马!”
typeof neverDeclared === typeof void 0
;-D
这很容易出错,因为实际上您只是依赖于未定义的某个变量(“未定义”)。正如其他帖子所示,这可能是错误的。 if(typeof neverDeclared === typeof undefined_variable_with_a_name_assumed_to_be_never_defined)
总是可以的,但是会很长。【参考方案4】:
您不必担心 undefined 被重命名。如果有人重命名未定义,那么如果检查失败,您将遇到更多麻烦。如果您真的想保护您的代码,请将其包装在 IFFE(立即调用的函数表达式)中,如下所示:
(function($, Backbone, _, undefined)
//undefined is undefined here.
)(jQuery, Backbone, _);
如果您在浏览器环境中使用全局变量(这已经是错误的),我会像这样检查 undefined:
if(window.neverDefined === undefined)
//Code works
由于全局变量是窗口对象的一部分,您可以简单地检查未定义而不是转换为字符串并比较字符串。
最重要的是,为什么你的变量没有定义?我看过很多代码,他们检查变量的存在并基于它执行一些操作。我从未见过这种方法在哪里是正确的。
【讨论】:
输入验证和依赖检查都是使用它的好理由。如果我的 Javascript 文件依赖于已加载的其他文件或已声明的初始化对象,那么测试文件依赖的对象或属性以防止未定义并抛出一个很好的异常而不是让您的脚本在不可预测的地方失败是很有用的。 听起来你可能需要 AMD (require.js) 中的一些东西 或者我可能只想做一个非常简单的比较,而不是在我的项目中包含另一个库:) 编辑太晚了 :(。想要添加 - require.js 也不是输入验证的正确解决方案(我在最初的评论中提到的 init 对象)。如果你有一个对象如果您希望在加载脚本之前填充某些值,那么如果未定义它们,则抛出异常很有用。 否,因为 typeof 返回一个字符串。所以 typeof undefined 返回“未定义”。 window.input !== undefined(如果你的变量在全局范围内)【参考方案5】:如果你真的担心 undefined 被重新定义,你可以使用一些辅助方法来防止这种情况发生:
function is_undefined(value)
var undefined_check; // instantiate a new variable which gets initialized to the real undefined value
return value === undefined_check;
这是有效的,因为当有人写 undefined = "foo"
时,他只让 name undefined
引用一个新值,但他不会更改 undefined
的实际值。
【讨论】:
但是,您现在引入了一个函数调用,这会损害性能。 我不认为这个函数调用会影响性能,DOM 更有可能成为瓶颈。但无论如何,如果您有通常包含库的大型匿名函数,您也可以在顶部定义undefined_check
,然后在代码中的任何地方使用它。
同意,我并不是说这是一个坏主意。值得指出的是,调用此函数的执行速度比执行typeof
检查要慢。
我认为这个函数很简单,可以内联,所以不会影响性能。
@TimDown:先写代码,这是可读的。第二次编写代码,这是可维护的,然后,如果它真的很慢。然后考虑性能。【参考方案6】:
您也可以使用 void 运算符来获取未定义的值:
if (input !== void 0)
// do stuff
(是的,如另一个答案中所述,如果未声明变量,这将引发错误,但这种情况通常可以通过代码检查或代码重构来排除,例如使用window.input !== void 0
进行测试全局变量或添加var input
。)
【讨论】:
【参考方案7】:我实际上遇到了 if (typeof input !== 'undefined')
在这种情况下它被用来提供默认函数参数:
function greet(name, greeting)
name = (typeof name !== 'undefined') ? name : 'Student';
greeting = (typeof greeting !== 'undefined') ? greeting : 'Welcome';
return `$greeting $name!`;
greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!
ES6 提供了以这种方式引入默认函数参数的新方法:
function greet(name = 'Student', greeting = 'Welcome')
return `$greeting $name!`;
greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!
这比第一个选项更简洁、更简洁。
【讨论】:
【参考方案8】:function greet(name, greeting)
name = (typeof name !== 'undefined') ? name : 'Student';
greeting = (typeof greeting !== 'undefined') ? greeting : 'Welcome';
console.log(greeting,name);
greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!
//ES6 provides new ways of introducing default function parameters this way:
function greet2(name = 'Student', greeting = 'Welcome')
// return '$greeting $name!';
console.log(greeting,name);
greet2(); // Welcome Student!
greet2('James'); // Welcome James!
greet2('Richard', 'Howdy'); // Howdy Richard!
【讨论】:
1) 同一个问题不需要回答 3 次。 2) 仅由代码组成的答案是一个糟糕的答案。你需要用英语解释......并将答案与所提出的问题联系起来。 3)您答案中的大部分代码与问题无关。【参考方案9】:(function()
var a= b = 3;
var ed = 103;
)();
//console.log(ed); //ed is not defined
console.log("a defined? " + (typeof a !== 'undefined')); //no define
console.log("b defined? " + (typeof b !== 'undefined')); //yes define
console.log(typeof(b)); //number
console.log(typeof(4+7)); //number
console.log(b); //3
console.log(typeof("4"+"7")); //string
var e= "ggg";
console.log(typeof(e)); //string
var ty=typeof(b);
console.log(ty); //number
console.log(typeof false); //boolean
console.log(typeof 1); //number
console.log(typeof 0); //number
console.log(typeof true); //boolean
console.log(typeof Math.tan); //function
console.log(typeof function()); //function
if(typeof neverDeclared == "undefined") //no errors
if(typeof neverDeclared === "undefined") //no errors
//if(neverDeclared == null) //showing error
console.log(typeof a:1); //object
console.log(typeof null); //object
console.log(typeof JSON); //object
console.log(typeof Math); //object
console.log(typeof /a-z/); //object
console.log(typeof new Date()); //object
console.log(typeof afbc); //undefined
//console.log(typeof new);//error
document.write("<br> * oprator as math ");
var r=14*"4";
document.write(r);
document.write("<br> + oprator as string ");
var r=14+"44";
document.write(r);
document.write("<br> Minus Operator work as mathematic ");
var r=64-"44";
document.write(r);
document.write("<br>");
console.log(typeof(4*"7")); //returns number
console.log(typeof(4+"7")); //returns string
Interview Question in JavaScript
【讨论】:
你能解释一下吗? typeof 返回六个可能的值:object、boolean、function、number、string 和 undefined。 typeof 运算符用于获取其操作数的数据类型(返回字符串)。操作数可以是文字或数据结构,例如变量、函数或对象。运算符返回数据类型。语法 typeof 操作数或 typeof(操作数) 1) 同一个问题不需要回答 3 次。 2) 仅由代码组成的答案是一个糟糕的答案。你需要用英语解释......并将答案与所提出的问题联系起来。 3)您答案中的大部分代码与问题无关。【参考方案10】:var bar = null;
console.log(typeof bar === "object"); //true yes
//because null a datatype of object
var barf = "dff";
console.log(typeof barf.constructor);//function
console.log(Array.isArray(bar));//falsss
console.log((bar !== null) && (bar.constructor === Object)); //false
console.log((bar !== null) && (typeof bar === "object")); // logs false
//because bar!==null, bar is a object
console.log((bar !== null) && ((typeof bar === "object") || (typeof bar === "function"))); //false
console.log(typeof bar === typeof object); //false
console.log(typeof bar2 === typeof undefined); //true
console.log(typeof bar3 === typeof undefinedff); //true
console.log(typeof bar2 == typeof undefined); //true
console.log((bar !== null) && (typeof bar === "object") && (toString.call(bar) !== "[object Array]")); //false
【讨论】:
1) 同一个问题不需要回答 3 次。 2) 仅由代码组成的答案是一个糟糕的答案。你需要用英语解释......并将答案与所提出的问题联系起来。 3)您答案中的大部分代码与问题无关。【参考方案11】:if (input == undefined) ...
工作得很好。当然不是null
比较,但我通常发现如果我需要区分undefined
和null
,我实际上更需要区分undefined
和任何false值,所以
else if (input) ...
会的。
如果一个程序重新定义undefined
,无论如何它真的是脑死。
我能想到的唯一原因是 IE4 兼容性,它不理解 undefined
关键字(不幸的是,这实际上不是关键字),但值当然可以 @987654329 @,所以你必须有这个:
var undefined;
上面的比较就可以了。
在您的第二个示例中,您可能需要双括号来使 lint 满意?
【讨论】:
您的input == undefined
将在null
输入上返回true
。以上是关于typeof !== "未定义" vs. != null的主要内容,如果未能解决你的问题,请参考以下文章