typeof!==“未定义”与!= null


491

我经常看到JavaScript代码以这种方式检查未定义的参数等:

if (typeof input !== "undefined") {
    // do stuff
}

这似乎有点浪费,因为它涉及类型查找和字符串比较,更不用说它的冗长了。这是必需的,因为undefined可以重命名。

我的问题是:
与该方法相比,该代码有何优势:

if (null != input) {
    // do stuff
}

据我所知,您无法重新定义null,因此不会意外中断。并且,由于!=运算符的类型强制,这将同时检查undefinednull...,而这恰恰是您想要的(例如,用于可选功能参数)。

但是,这种形式似乎并不广泛,它甚至导致JSLint对使用邪恶!=运算符的人大喊。

为什么认为这种风格不好?


13
@ Marcel,没有真正的区别,但是有两个原因。其一,对于某些人来说,阅读起来更加清晰。第二个原因是,它可以防止意外覆盖变量。您是否曾经打算这样做:if(foo =“ value”)打算进行比较时。如果您习惯在赋值/比较运算符中反转变量,那么就不会有问题。
2011年

29
对于某些人(包括我)来说,这实际上更难以阅读。另外,大多数IDE都会警告您意外分配。但是如果比较的变量很长,我仍然使用这种形式。YMMV。
johndodo

15
@MarcelKorpel这称为“ Yoda条件”:umumble.com/blogs/Programming/321
kol

55
更难阅读。人们不会说“瓶子不空”。
Noel Abrahams,2012年

11
if (null != input)对讲英语的人来说只是“ Yoda Speak”(我是.... uuammmmm),所以如果他们等同于同一件事,那实际上只是语义。恕我直言。
webLacky3rdClass 2013年

Answers:


709

typeof 比较安全,因为它允许从未声明过标识符:

if(typeof neverDeclared === "undefined") // no errors

if(neverDeclared === null) // throws ReferenceError: neverDeclared is not defined

3
if(((typeof neverDeclared!==“ undefined”)&&(neverDeclared!== null)){返回true; } else {返回false;}
Anthony DiSanti

88
与null / undefined比较时使用===。
MyGGaN 2012年

47
@MyGGaN仅在您要区分两者时。在许多情况下,==可能会更好,因为它会同时测试null和undefined。
seanmonstar 2012年

10
我找不到typeof somevar =='undefined'和typeof somevar ==='undefined'之间的任何区别,因为typeof总是返回字符串。如果为null,它将返回'object'。还是我错了?
TomTom

2
我相信@TomTom的评论是问题的症结所在-我不明白为什么在比较一个类型为字符串的值时为什么要使用!==or ===运算符。
Nicolas Rinaudo

49

如果声明了变量(使用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

1
如果已经定义了undefined,那么您是否会通过名为undefined的参数将其传递给匿名函数,却一事无成?
Anthony DiSanti 2010年

20
@Anthony DiSanti:否,undefined是函数参数的名称,而不是其值。没有任何内容传递给该函数,这意味着第一个参数的值是不确定的。
乔伊·亚当斯

3
啊,我的错,谢谢您的跟进。我删除了我的投票,对此表示抱歉。
安东尼·迪桑蒂

2
当您可以正确地开始时,为什么要编写一个异常来处理另一个开发人员声明的未定义?jQuery封装了您在函数中显示的初始匿名函数,以确保未定义未定义并减小最小大小。简而言之,如果这样做可以带来意想不到的结果,为什么还要冒险进行延迟编程以避免输入错误(typeof variable ==='undefined')。如果我们想要(typeof变量==='对象')该怎么办,我们是否应该提供一个也是对象的默认变量,以便我们可以做(变量===对象)?
fyrye 2014年

28

好办法:

if(typeof neverDeclared == "undefined") //no errors

但是最好看的方法是通过检查:

if(typeof neverDeclared === typeof undefined) //also no errors and no strings

6
var undefined = function(){}; if(typeof neverDeclared === typeof undefined); neverDecalred!='功能'; jsfiddle.net/hbPZ5返回typeof var; 返回一个字符串。没有错误或字符串,但不会总是给出预期的结果。授予的开发人员不应声明未定义,但可以使用某些框架和库。
fyrye 2014年

1
我主要使用, if (typeof neverDeclared === typeof undefined) { 但是Lint会引发错误。“期望一个字符串,而是看到了'typeof'。” 您如何解决这个错误?我们应该服从Lint的要求,而是使用“好的方法”吗?
Ayelis

2
@fyrye您知道实际上有任何未定义的JavaScript库/框架吗?我知道有可能 但我想举一个疯狂的例子:“在这里您可能会遇到这种讨厌的牛羚!”
bigtunacan

4
typeof neverDeclared === typeof void 0;-D
亚历亚罗舍维奇

1
这很容易出错,因为实际上您只是依赖于未定义的某个变量(“未定义”)。如其他帖子所示,这可能是错误的。您可以随时做,if(typeof neverDeclared === typeof undefined_variable_with_a_name_assumed_to_be_never_defined) {但是时间很长。
皮埃尔·奥利维尔·瓦雷斯

12

您不必真正担心未定义的重命名。如果某人重命名了undefined,那么如果检查失败,您将面临的麻烦远不止几个。如果您真的想保护您的代码,则将其包装在IFFE(立即调用的函数表达式)中,如下所示:

(function($, Backbone, _, undefined) {
    //undefined is undefined here.
})(jQuery, Backbone, _);

如果您正在浏览器环境中使用全局变量(已经是错误的),我将检查未定义的内容,如下所示:

if(window.neverDefined === undefined) {
    //Code works
}

由于全局变量是window对象的一部分,因此您可以简单地检查undefined而不是强制转换为字符串并比较字符串。

最重要的是,为什么没有定义变量?我看过很多代码,它们在其中检查变量的存在并基于此执行一些操作。我从未见过这种方法正确的地方。


1
输入验证和依赖性检查都是使用此功能的良好理由。如果我的Javascript文件依赖于已加载的其他文件或已声明了初始化对象,则对未定义的文件依赖的对象或属性进行测试很有用,并抛出一个不错的异常,而不是让脚本在无法预测的地方失败。
AmericanUmlaut

听起来您可能需要AMD(require.js)的产品
Peeter

1
或者我可能只是想做一个非常简单的比较,而不是在我的项目中包括另一个库:)
AmericanUmlaut

来不及编辑:(.。想要添加-require.js也不是用于输入验证的正确解决方案(我在最初的评论中提到的init对象)。如果您有一个对象,您希望其中填充了某些对象值加载脚本之前,如果未定义则抛出异常很有用
AmericanUmlaut

1
否,因为typeof返回一个字符串。因此,typeof undefined返回“ undefined”。window.input!==未定义(如果您的变量在全局云中)
Peeter

5

如果您真的担心未定义会被重新定义,则可以使用以下一些辅助方法来防止这种情况:

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"他只允许名称 undefined引用一个新值,但他不更改的实际值undefined


1
但是,您现在引入了一个函数调用,这会损害性能。
Tim Down'4

我认为此函数调用不会降低性能,而DOM成为瓶颈的可能性更大。但是无论如何,如果您有一个通常的大型匿名函数来包含您的库,您也可以undefined_check在顶部进行定义,然后在代码中的任何地方使用它。
Ivo Wetzel

1
同意,我并不是说这是一个坏主意。只需指出,调用此函数将比执行typeof检查慢。
Tim Down'4

我认为此函数非常简单,可以内联,因此性能不会受到影响。
huyz 2011年

4
@TimDown:首先编写代码,这是可读的。第二次编写代码,这是可维护的,然后,如果真的很慢的话。然后考虑性能。
Andreas

4

您还可以使用void运算符获取未定义的值:

if (input !== void 0) {
    // do stuff    
}

(是的,如另一个答案所述,如果未声明变量,这将引发错误,但是这种情况通常可以通过代码检查或代码重构(例如window.input !== void 0用于测试全局变量或添加var input)来排除。)


1

我实际上遇到过(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!

这比第一种选择更冗长,更简洁。


1

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!


0

(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


你能提供一个解释吗?
jhpratt GOFUNDME授权

typeof返回六个可能的值:对象,布尔值,函数,数字,字符串和未定义。typeof运算符用于获取其操作数的数据类型(返回字符串)。操作数可以是文字或数据结构,例如变量,函数或对象。操作员返回数据类型。语法typeof操作数或typeof(操作数)
Avinash Maurya

0

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


-7
if (input == undefined) { ... }

效果很好。当然,这不是一个null比较,但是我通常会发现,如果需要区分undefinednull,实际上我实际上需要区分undefined和,只是任何假值,因此

else if (input) { ... }

可以。

如果一个程序重新定义,undefined那真是脑筋急转弯。

我能想到的唯一原因是为了实现IE4兼容性,它不能理解undefined关键字(不幸的是,它实际上不是关键字),但是当然值可以 undefined,因此您必须具有以下特性:

var undefined;

和上面的比较就可以了。

在第二个示例中,您可能需要用双括号使皮棉快乐?


input == undefined将返回true上一个null输入。
mgol
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.