web-dev-qa-db-ja.com

JavaScriptで "未定義"をチェックするにはどうすればいいですか?

JavaScriptで変数が未定義かどうかをテストするための最も適切な方法は何ですか?私はいくつかの可能な方法を見ました:

if (window.myVariable)

または

if (typeof(myVariable) != "undefined")

または

if (myVariable) //This throws an error if undefined. Should this be in Try/Catch?
2136
random65537

変数がその値に関係なく宣言されているかどうかを調べたい場合は、in演算子を使用するのが最も安全な方法です。この例を考えてください。

// global scope
var theFu; // theFu has been declared, but its value is undefined
typeof theFu; // "undefined"

しかし、変数やプロパティは宣言されていても初期化されていないため、これは意図した結果ではない場合があります。より堅牢なチェックにはin演算子を使用してください。

"theFu" in window; // true
"theFoo" in window; // false

変数が宣言されていないのか、値undefinedを持っているのかを知りたい場合は、typeof演算子を使用してください。

if (typeof myVar !== 'undefined')

typeof演算子は文字列を返すことが保証されています。 undefinedは上書きされる可能性があるため、undefinedに対する直接比較は面倒です。

window.undefined = "omg";
"omg" == undefined // true

@CMSが指摘したように、これはECMAScript第5版で修正されており、undefinedは書き込み不可です。

if (window.myVar)にはこれらの誤った値も含まれるため、それほど堅牢ではありません。

 false 
 0 "
 NaN 
 null 
未定義

あなたの3番目のケース - if (myVariable)も2つのケースでエラーを投げることができることを指摘してくれた@CMSに感謝します。 1つ目は、変数が定義されていないときで、これによりReferenceErrorがスローされます。

// abc was never declared.
if (abc) {
    // ReferenceError: abc is not defined
} 

もう1つのケースは、変数が定義されていても、呼び出されたときにエラーをスローするgetter関数を持っている場合です。例えば、

// or it's a property that can throw an error
Object.defineProperty(window, "myVariable", { 
    get: function() { throw new Error("W00t?"); }, 
    set: undefined 
});
if (myVariable) {
    // Error: W00t?
}
2403
Anurag

私は個人的に使います

myVar === undefined

警告:=====よりも上で使用されており、myVarは以前に 宣言されています defined ではありません)。


私はtypeof myVar === "undefined"が好きではありません。私はそれが長い間そして不必要であると思う。 (私はより少ないコードで同じことをすることができます。)

今、何人かの人々はこれを読んだときに痛みに悩まされるでしょう、「叫んで!WAAITTT !!! undefinedは再定義できます!」と叫んで。

クール。私はこれを知っている。繰り返しますが、Javascriptのほとんどの変数は再定義できます。再定義できる組み込みの識別子を使用しないでください。

あなたがこの規則に従えば、あなたには良いことです。あなたは偽善者ではありません。

重要なことは、JSで実際に多くの作業を行うためには、開発者は定義可能な識別子を信頼できるものにする必要があります。誰かがすることができるので私はsetTimeoutを使用すべきでないと人々が私に言うのを聞きません

window.setTimeout = function () {
    alert("Got you now!");
};

つまり、生の=== undefinedを使わないという "再定義可能"引数は偽です。

(まだundefinedが再定義されるのを恐れているのなら、未テストのライブラリコードをあなたのコードベースに盲目的に統合しているのはなぜでしょうか?それとももっと簡単です:リンティングツールです。)


また、typeofアプローチのように、このテクニックは宣言されていない変数を "検出"することができます。

if (window.someVar === undefined) {
    doSomething();
}

しかし、これらのテクニックは両方とも抽象化に漏れています。私はあなたがこれを使用しないように、あるいは

if (typeof myVar !== "undefined") {
    doSomething();
}

検討してください:

var iAmUndefined;

その変数が宣言されているかどうかをキャッチするには、in演算子に頼る必要があるかもしれません。 (多くの場合、あなたは単にコードO_oを読むことができます)。

if ("myVar" in window) {
    doSomething();
}

ちょっと待って!もっとあります!もしプロトタイプチェーンの魔法が起こっていたら…?優れたin演算子でさえ十分ではありません。 (さて、私はこの部分についてここでやっていますが、99%の時間で=== undefined(そして**** cough **** typeof)は問題なく動作すると言っています。自分自身で件名)

1009
Thomas Eding

typeofを使うのが私の好みです。 ==演算子または===演算子との比較やifを使用した型強制とは異なり、変数が宣言されていないときに機能します。 (undefinedは、nullとは異なり、ECMAScript 3環境でも再定義される可能性があるため、比較には信頼できませんが、現在ではほとんどすべての一般的な環境がECMAScript 5以上に準拠しています)。

if (typeof someUndeclaredVariable == "undefined") {
    // Works
}

if (someUndeclaredVariable === undefined) { 
    // Throws an error
}
167
Tim Down

typeofを使う必要があります。

if (typeof something != "undefined") {
    // ...
}
57
Jacob Relkin

アップデート2018-07-25

この記事が最初に書かれてから約5年が経ち、JavaScriptが大きく進歩しました。元の記事でテストを繰り返すと、次のテスト方法の間で一貫した違いはありませんでした。

  • abc === undefined
  • abc === void 0
  • typeof abc == 'undefined'
  • typeof abc === 'undefined'

Chromeがテストを最適化しないようにテストを変更した場合でも、違いはわずかです。そのため、わかりやすくするためにabc === undefinedをお勧めします。

chrome://versionの関連コンテンツ:

  • Google Chrome:67.0.3396.99(公式ビルド)(64ビット)(コホート:安定版)
  • リビジョン:a337fbf3c2ab8ebc6b64b0bfdce73a20e2e2252b-refs/branch-heads/3396 @ {#790}
  • OS:ウィンドウズ
  • JavaScript:V8 6.7.288.46
  • ユーザーエージェント:Mozilla/5.0(Windows NT 10.0; Win64; x 64)AppleWebKit/537.36(GeckoのようなKHTML)Chrome/67.0.3396.99 Safari/537.36

オリジナルの投稿2013-11-01

Google Chromeでは、次のテストがtypeofテストよりもやや高速です。

if (abc === void 0) {
    // Undefined
}

違いはごくわずかでした。しかし、このコードはより簡潔で、void 0が何を意味するのかを知っている人には一目瞭然です。ただし、abc はまだ と宣言する必要があります。

typeofvoidはどちらも、undefinedと直接比較するよりもかなり高速でした。 Chrome開発者コンソールで次のテスト形式を使用しました。

var abc;
start = +new Date();
for (var i = 0; i < 10000000; i++) {
    if (TEST) {
        void 1;
    }
}
end = +new Date();
end - start;

結果は以下の通りです。

Test: | abc === undefined      abc === void 0      typeof abc == 'undefined'
------+---------------------------------------------------------------------
x10M  |     13678 ms               9854 ms                 9888 ms
  x1  |    1367.8 ns              985.4 ns                988.8 ns

最初の行は milli secondsで、2行目は nano secondsです。 3.4ナノ秒の違いは何もありません。その後のテストでは、時間はかなり一貫していました。

31
Zenexer

未定義の場合、文字列は未定義ではないため、文字 "undefined"を含む文字列と同じにはなりません。

変数の型を確認することができます。

if (typeof(something) != "undefined") ...

時々あなたはタイプさえチェックする必要がない。変数の値が設定時にfalseに評価できない場合(たとえば関数の場合)、変数を評価するだけで済みます。例:

if (something) {
  something(param);
}
20
Guffa

さまざまな答えの結果を示すいくつかのシナリオ: http://jsfiddle.net/drzaus/UVjM4/ /

(スコープ付きラッパーではvarテストにinを使用すると効果が異なります)

参照用コード:

(function(undefined) {
    var definedButNotInitialized;
    definedAndInitialized = 3;
    someObject = {
        firstProp: "1"
        , secondProp: false
        // , undefinedProp not defined
    }
    // var notDefined;

    var tests = [
        'definedButNotInitialized in window',
        'definedAndInitialized in window',
        'someObject.firstProp in window',
        'someObject.secondProp in window',
        'someObject.undefinedProp in window',
        'notDefined in window',

        '"definedButNotInitialized" in window',
        '"definedAndInitialized" in window',
        '"someObject.firstProp" in window',
        '"someObject.secondProp" in window',
        '"someObject.undefinedProp" in window',
        '"notDefined" in window',

        'typeof definedButNotInitialized == "undefined"',
        'typeof definedButNotInitialized === typeof undefined',
        'definedButNotInitialized === undefined',
        '! definedButNotInitialized',
        '!! definedButNotInitialized',

        'typeof definedAndInitialized == "undefined"',
        'typeof definedAndInitialized === typeof undefined',
        'definedAndInitialized === undefined',
        '! definedAndInitialized',
        '!! definedAndInitialized',

        'typeof someObject.firstProp == "undefined"',
        'typeof someObject.firstProp === typeof undefined',
        'someObject.firstProp === undefined',
        '! someObject.firstProp',
        '!! someObject.firstProp',

        'typeof someObject.secondProp == "undefined"',
        'typeof someObject.secondProp === typeof undefined',
        'someObject.secondProp === undefined',
        '! someObject.secondProp',
        '!! someObject.secondProp',

        'typeof someObject.undefinedProp == "undefined"',
        'typeof someObject.undefinedProp === typeof undefined',
        'someObject.undefinedProp === undefined',
        '! someObject.undefinedProp',
        '!! someObject.undefinedProp',

        'typeof notDefined == "undefined"',
        'typeof notDefined === typeof undefined',
        'notDefined === undefined',
        '! notDefined',
        '!! notDefined'
    ];

    var output = document.getElementById('results');
    var result = '';
    for(var t in tests) {
        if( !tests.hasOwnProperty(t) ) continue; // bleh

        try {
            result = eval(tests[t]);
        } catch(ex) {
            result = 'Exception--' + ex;
        }
        console.log(tests[t], result);
        output.innerHTML += "\n" + tests[t] + ": " + result;
    }
})();

そして結果:

definedButNotInitialized in window: true
definedAndInitialized in window: false
someObject.firstProp in window: false
someObject.secondProp in window: false
someObject.undefinedProp in window: true
notDefined in window: Exception--ReferenceError: notDefined is not defined
"definedButNotInitialized" in window: false
"definedAndInitialized" in window: true
"someObject.firstProp" in window: false
"someObject.secondProp" in window: false
"someObject.undefinedProp" in window: false
"notDefined" in window: false
typeof definedButNotInitialized == "undefined": true
typeof definedButNotInitialized === typeof undefined: true
definedButNotInitialized === undefined: true
! definedButNotInitialized: true
!! definedButNotInitialized: false
typeof definedAndInitialized == "undefined": false
typeof definedAndInitialized === typeof undefined: false
definedAndInitialized === undefined: false
! definedAndInitialized: false
!! definedAndInitialized: true
typeof someObject.firstProp == "undefined": false
typeof someObject.firstProp === typeof undefined: false
someObject.firstProp === undefined: false
! someObject.firstProp: false
!! someObject.firstProp: true
typeof someObject.secondProp == "undefined": false
typeof someObject.secondProp === typeof undefined: false
someObject.secondProp === undefined: false
! someObject.secondProp: true
!! someObject.secondProp: false
typeof someObject.undefinedProp == "undefined": true
typeof someObject.undefinedProp === typeof undefined: true
someObject.undefinedProp === undefined: true
! someObject.undefinedProp: true
!! someObject.undefinedProp: false
typeof notDefined == "undefined": true
typeof notDefined === typeof undefined: true
notDefined === undefined: Exception--ReferenceError: notDefined is not defined
! notDefined: Exception--ReferenceError: notDefined is not defined
!! notDefined: Exception--ReferenceError: notDefined is not defined
17
drzaus
if (typeof foo == 'undefined') {
 // Do something
};

typeofは常に文字列を返すので、この場合、厳密な比較(!==)は不要です。

16
Mathias Bynens

この記事で 私は Underscore.js のようなフレームワークを読んでいます:

function isUndefined(obj){
    return obj === void 0;
}
15
Marthijn

個人的には、私はいつも以下を使います:

var x;
if( x === undefined) {
    //Do something here
}
else {
   //Do something else here
}

Window.undefinedプロパティは、最近のすべてのブラウザ(JavaScript 1.8.5以降)では書き込みできません。 Mozillaのドキュメントから: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined 、私はこれを見ています:typeof()を使用する理由の1つはそうではないということです変数が定義されていない場合はエラーをスローします。

私は使うというアプローチが好きです

x === undefined 

xが以前に宣言されていなければ、それは失敗して私の顔にはげなく爆破します。これはxが宣言されていないことを私に警告する。 JavaScriptで使用されているすべての変数は宣言されるべきだと思います。

11
Hrishi

私がundefinedをチェックする最も信頼できる方法はvoid 0を使うことです。

これは新旧のブラウザと同様に互換性があり、window.undefinedが場合によってはそうであるように上書きすることができません。

if( myVar === void 0){
    //yup it's undefined
}
10
Joseph Gabriel

他の答えのどれも私を助けなかったので、私はこれをすることを提案する。それはInternet Explorer 8で私のために働きました:

if (typeof variable_name.value === 'undefined') {
    // variable_name is undefined
}
4
anmarti

@Thomas Edingの反対の答え:

コードでmyVarを宣言するのを忘れた場合は、myVar is not definedが返されます。

実際の例を見てみましょう。

私は変数名を使っていますが、それがどこかで宣言されているかどうかはわかりません。

それから@ Anuragの答えが役立ちます。

var myVariableToCheck = 'myVar';
if (window[myVariableToCheck] === undefined)
    console.log("Not declared or declared, but undefined.");

// Or you can check it directly 
if (window['myVar'] === undefined) 
    console.log("Not declared or declared, but undefined.");
3
Vikas
// x has not been defined before
if (typeof x === 'undefined') { // Evaluates to true without errors.
   // These statements execute.
}

if (x === undefined) { // Throws a ReferenceError

}
3
sourcecode
    var x;
    if (x === undefined) {
        alert ("I am declared, but not defined.")
    };
    if (typeof y === "undefined") {
        alert ("I am not even declared.")
    };

    /* One more thing to understand: typeof ==='undefined' also checks 
       for if a variable is declared, but no value is assigned. In other 
       words, the variable is declared, but not defined. */

    // Will repeat above logic of x for typeof === 'undefined'
    if (x === undefined) {
        alert ("I am declared, but not defined.")
    };
    /* So typeof === 'undefined' works for both, but x === undefined 
       only works for a variable which is at least declared. */

    /* Say if I try using typeof === undefined (not in quotes) for 
       a variable which is not even declared, we will get run a 
       time error. */

    if (z === undefined) {
        alert ("I am neither declared nor defined.")
    };
    // I got this error for z ReferenceError: z is not defined 
2
Gaurav

私はそれを関数のパラメータとして使用し、関数の実行時にそれを除外することで、 "実際の"定義が未定義になります。それはあなたのコードを関数の中に入れることを要求しますが。私はjQueryのソースを読みながらこれを見つけました。

undefined = 2;

(function (undefined) {
   console.log(undefined); // prints out undefined
   // and for comparison:
   if (undeclaredvar === undefined) console.log("it works!")
})()

もちろんtypeofを使うこともできます。しかし、私のコードはすべて包含関数の中にあるのが普通なので、この方法を使用すると、あちこちで数バイト節約できます。

0