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

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

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

我的问题是: 这段代码比下面的方法好到哪里去了:

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

据我所知,你不能重定义null,所以它不会意外中断。并且,由于!=操作符的类型强制,这将检查undefined和null…这通常正是你想要的(例如,对于可选的函数参数)。

然而,这种形式似乎并不普遍,它甚至会导致JSLint因为您使用了邪恶的!=操作符而对您大喊大叫。

为什么这被认为是糟糕的风格?


当前回答

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

这比第一个选项更简洁。

其他回答

你也可以使用void操作符来获得一个未定义的值:

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

(是的,正如另一个答案所指出的,如果变量没有声明,这将抛出一个错误,但这种情况通常可以通过代码检查或代码重构来排除,例如使用window。输入!== void 0测试全局变量或添加var输入)

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!

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

这比第一个选项更简洁。

Typeof更安全,因为它允许标识符之前从未声明过:

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

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

你不应该真的担心undefined被重命名。如果有人重命名为undefined,那么您将遇到比检查失败更多的麻烦。如果你真的想保护你的代码,把它包装在IFFE(立即调用的函数表达式)中,就像这样:

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

如果你在浏览器环境中使用全局变量(这已经是错误的),我会像这样检查undefined:

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

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

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