typeof!==「未定義」と!= null


491

次のように、未定義のパラメータなどをチェックするJavaScriptコードをよく見ます。

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

冗長性は言うまでもなく、型の検索と文字列の比較の両方が含まれるため、これは一種の無駄に見えます。undefined名前を変更できるので必要です。

私の質問は次のとおり
です。そのコードはこのアプローチよりも優れています:

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

私の知る限り、を再定義することはできないnullため、予期せず壊れることはありません。そして、!=演算子の型強制のため、これはundefinedandとnull...の両方をチェックします。これは、多くの場合、正確に必要なものです(たとえば、オプションの関数パラメーター)。

しかし、このフォームは広く普及していないようであり、JSLintが邪悪な!=演算子を使用していることを怒鳴りつけます。

なぜこれが悪いスタイルと考えられているのですか?


13
@マルセル、本当の違いはありませんが、それを行うには2つの理由があります。1つは、一部の人にとっては読みやすくなります。2番目の理由は、変数が誤って上書きされるのを防ぐためです。これを行ったことはありますか:if(foo = "value")比較を行うつもりの場合。代入演算子/比較演算子で変数を逆にする癖がついたら、その問題は発生しません。
Layke、2011年

29
一部の人(私を含む)にとって、これは実際には読みにくいです。また、ほとんどのIDEは偶発的な割り当てについて警告します。しかし、比較される変数が非常に長い場合でも、このフォームを使用します。YMMV。
johndodo 2012

15
@MarcelKorpelこれは「ヨーダ条件」と呼ばれます:umumble.com/blogs/Programming/321
kol

55
読みにくいです。「空っぽではない」とは言わない。
ノエルアブラハム

11
if (null != input)英語の話者にとっては「ヨーダスピーク」だけです(1人は私は.... uuammmmmです)。したがって、それらが同じものに等しい場合、それは実際には単なるセマンティクスです。私見では。
webLacky3rdClass 2013年

回答:


710

typeof 識別子が以前に宣言されたことがないため、より安全です。

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

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

3
if((typeof neverDeclared!== "undefined")&&(neverDeclared!== null)){return true; } else {falseを返す; }
Anthony DiSanti

88
null / undefinedと比較する場合は===を使用します。
MyGGaN

47
@MyGGaNは、この2つを区別したい場合のみ。多くの場合、==nullと未定義の両方をテストするので、より良い場合があります。
seanmonstar 2012年

10
typeofは常に文字列を返すため、typeof somevar == 'undefined'とtypeof somevar === 'undefined'の違いはわかりません。nullの場合は「オブジェクト」を返します。それとも私が間違っているのでしょうか?
TomTom 2013

2
私は@TomTomのコメントが問題の核心であると信じています- 文字列であることがわかっている型の値を比較するときに!==or ===演算子を使用する理由を理解できません。
Nicolas Rinaudo 2013

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

20
@Anthony DiSanti:いいえ、undefined値ではなく関数パラメーターに付けられた名前です。関数には何も渡されません。つまり、最初のパラメーターの値は未定義です。
Joey Adams、

3
ああ私の間違い、フォローアップしてくれてありがとう。投票を削除しました。申し訳ありません。
Anthony DiSanti、2011年

2
最初から正しく行うことができるのに、別の開発者が宣言した未定義を処理するために例外を書くのはなぜですか?jQueryは、関数に表示される初期の無名関数をラップして、未定義が定義されていないことを確認し、縮小サイズを減らします。この方法で行うと予期しない結果が出る可能性がある場合は、単純に言えば、怠惰なプログラミングがタイプアウトを回避するリスクがあるのはなぜですか(typeof variable === 'undefined')。必要な場合(typeof variable === 'object')、デフォルトの変数であるオブジェクトも提供して、(variable === object)を実行できますか?
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 return typeof var; 文字列を返します。エラーや文字列はありませんが、常に期待どおりの結果が得られるとは限りません。認められた開発者はundefinedを宣言すべきではありませんが、宣言するフレームワークとライブラリがいくつかあります。
fyrye 2014年

1
主に使用してif (typeof neverDeclared === typeof undefined) { います が、Lintはエラーをスローします。「文字列が必要ですが、代わりに「typeof」が見つかりました。」このエラーをどのように回避しますか?Lintの要求に従い、代わりに「良い方法」を使用する必要がありますか?
2015年

2
@fyrye実際に未定義に変化するJavaScriptライブラリ/フレームワークを知っていますか?私はそれが可能であることを知っています。しかし、「ここでは、この厄介なヌーに遭遇するかもしれません!」というワイルドな例を見つけたいと思います。
bigtunacan

4
typeof neverDeclared === typeof void 0;-D
Alex Yaroshevich

1
実際には、定義されていない特定の変数(「未定義」)に依存しているため、エラーが発生しやすくなります。他の投稿が示したように、これは間違っている可能性があります。いつでもできますif(typeof neverDeclared === typeof undefined_variable_with_a_name_assumed_to_be_never_defined) {が、かなり長いです。
Pierre-Olivier Vares 2017

12

未定義の名前が変更されることを心配する必要はありません。誰かがundefinedの名前を変更すると、チェックが失敗した場合に、ほんの数人よりもはるかに多くの問題が発生します。本当にコードを保護したい場合は、次のようにコードをIFFE(すぐに呼び出される関数式)でラップします。

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

ブラウザー環境でグローバル変数(既に間違っている)を操作している場合は、次のようにundefinedをチェックします。

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

グローバル変数はウィンドウオブジェクトの一部であるため、文字列にキャストして文字列を比較する代わりに、未定義に対して単にチェックできます。

その上、なぜ変数が定義されていないのですか?変数の存在を確認し、それに基づいていくつかのアクションを実行する多くのコードを見てきました。このアプローチがどこで正しいのか一度も見たことがありません。


1
入力の検証と依存関係のチェックの両方が、これを使用する良い理由です。ロードされている他のファイルに依存するJavascriptファイルがある場合、またはオブジェクトが宣言されているので、スクリプトが予期しない場所で失敗するのではなく、ファイルが未定義に対して依存しているオブジェクトまたはプロパティをテストし、素敵な例外をスローすると便利です。
AmericanUmlaut

AMD(require.js)のラインで何かが必要かもしれません
Peeter

1
または、プロジェクトに別のライブラリを含めるのではなく、非常に単純な比較を行いたいだけかもしれません:)
AmericanUmlaut

編集が遅すぎます:(。追加したかった-require.jsも入力検証の適切なソリューションではありません(最初のコメントで述べたinitオブジェクト)。スクリプトがロードされる前の値で、定義されていない場合は例外をスローすると便利です
AmericanUmlaut

1
いいえ、typeofは文字列を返すためです。したがって、typeof undefinedは「undefined」を返します。window.input!== undefined(変数がグローバルスポークにある場合)
Peeter

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"にのみ許可し、実際の値は変更しないためです。 undefinedundefined


1
ただし、ここではパフォーマンスを低下させる関数呼び出しを導入しました。
Tim Down

この関数呼び出しによってパフォーマンスが低下することはないと思います。DOMがボトルネックになる可能性がはるかに高くなります。しかし、とにかく、ライブラリを何でも含む通常の大きな無名関数がある場合は、最初に定義undefined_checkして、コードのどこでも使用できます。
Ivo Wetzel 2010

1
同意し、これは悪い考えだとは言っていません。この関数を呼び出すと、typeofチェックを実行するよりもパフォーマンスが低下することに注意してください。
Tim Down

この関数は、インライン化できるほど単純なので、パフォーマンスには影響しません。
huyz

4
@TimDown:最初にコードを書く、それは読みやすい。次に、コードを記述します。それは保守可能であり、それが本当に遅くなる場合です。次に、パフォーマンスについて考えます。
andreas 2013年

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 RELICENSING '13 / 09/13

typeofが返す可能性のある値は、オブジェクト、ブール値、関数、数値、文字列、および未定義の6つです。typeof演算子は、そのオペランドのデータ型(文字列を返す)を取得するために使用されます。オペランドは、リテラル、または変数、関数、オブジェクトなどのデータ構造のいずれかです。演算子はデータ型を返します。構文typeofオペランドまたはtypeof(オペランド)
Avinash Maurya '13

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比較ではありませんが、通常、undefinedとを区別する必要がある場合はnull、実際にはとundefinedfalse値を区別する必要があるため、

else if (input) { ... }

それを行います。

プログラムが再定義undefinedした場合、とにかくそれは本当に頭の痛いです。

私が考えることができる唯一の理由はIE4互換性のためでした、それはundefinedキーワード(実際にはキーワードではありませんが、残念ながら)を理解していませんでしたが、もちろん値がである可能性 undefinedあるので、これが必要でした:

var undefined;

上記の比較はうまくいきます。

2番目の例では、lintを幸せにするためにおそらく二重括弧が必要ですか?


あなたがinput == undefined返されますtruenull入力。
mgol 2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.