web-dev-qa-db-ja.com

変数=== undefinedとtypeof変数=== "undefined"

jQuery Core Style Guidelines は、変数が定義されているかどうかを確認する2つの異なる方法を提案しています。

  • グローバル変数:typeof variable === "undefined"
  • ローカル変数:variable === undefined
  • プロパティ:object.prop === undefined

JQueryがグローバル変数に対して1つのアプローチを使用し、ローカルおよびプロパティに対して別のアプローチを使用するのはなぜですか?

272

宣言されていない変数の場合、typeof fooは文字列リテラル"undefined"を返しますが、IDチェックfoo === undefinedはエラーをトリガーします"foo is not defined"

ローカル変数(knowがどこかで宣言されている)の場合、このようなエラーは発生しないため、IDチェックが行われます。

329
Linus Kleen

どこでもtypeof foo === "undefined"を使用することに固執します。それは決してうまくいかない。

JQueryが2つの異なるメソッドを推奨する理由は、jQueryコードが存在する関数内で独自のundefined変数を定義しているため、その関数内でundefinedが外部から改ざんされないためです。また、誰かが2つの異なるアプローチのベンチマークを行い、foo === undefinedの方が高速であるため、その方法を決定したことも想像できます。 [更新:コメントに記載されているように、undefinedとの比較もわずかに短く、これは考慮事項となる可能性があります。]ただし、実際の状況でのゲインまったく重要ではありません。このチェックは決してボトルネックにはなりません。また、失うものは重要です。比較のためにHostオブジェクトのプロパティを評価すると、typeofチェックは決してエラーになりません。

たとえば、XMLを解析するためにIEで次が使用されます。

var x = new ActiveXObject("Microsoft.XMLDOM");

loadXMLメソッドがあるかどうかを安全に確認するには:

typeof x.loadXML === "undefined"; // Returns false

一方:

x.loadXML === undefined; // Throws an error

UPDATE

言及し忘れたtypeofチェックのもう1つの利点は、foo === undefinedチェックでは機能しない未宣言の変数でも機能し、実際にはReferenceErrorがスローされることです。思い出させてくれた@LinusKleenに感謝します。例えば:

typeof someUndeclaredVariable; // "undefined"
someUndeclaredVariable === undefined; // throws a ReferenceError

結論:常にtypeofチェックを使用します。

110
Tim Down

Typeof-variantを使用するもう1つの理由:undefinedを再定義できます。

undefined = "foo";
var variable = "foo";
if (variable === undefined)
  console.log("eh, what?!");

typeof variableの結果はできません。

更新:ES5ではそうではないことに注意してください。

26
Jakob

variable === undefinedのパフォーマンスの向上に関心のある方は、こちらをご覧ください。ただし、これはchrome最適化のみのようです。

6
RiZKiT

undefinedは常に宣言されているわけではありませんが、jQueryはそのメイン関数でundefinedを宣言しているためです。したがって、内部では安全なundefined値を使用しますが、外部では安全にするためにtypeofスタイルを使用します。

6
Struppi

概要:

グローバルスコープで、変数が宣言されていないか、値undefinedを持っている場合、実際にtrueを返します。

var globalVar1;

// This variable is declared, but not defined and thus has the value undefined
console.log(globalVar1 === undefined);

// This variable is not declared and thus will throw a referenceError
console.log(globalVar2 === undefined);

グローバルスコープでは、変数が宣言されているかどうかが100%わからないため、referenceErrorが発生する可能性があります。未知の変数に対してtypeof演算子を使用すると、変数が宣言されていない場合、この問題は発生しません。

var globalVar1;

console.log(typeof globalVar1 === 'undefined');
console.log(typeof globalVar2 === 'undefined');

これは、変数が宣言されていないか、現在値typeofを保持しているときにundefined演算子が文字列undefinedを返すためです。


  • ローカル変数では、この変数が存在することを事前に知っているため、この問題はありません。変数が存在する場合、それぞれの関数を単純に調べることができます。
  • オブジェクトプロパティでは、存在しないオブジェクトプロパティを検索しようとすると、値undefinedも取得されるため、この問題は発生しません。
var obj = {};

console.log(obj.myProp === undefined);
1

ローカル変数の場合、localVar === undefinedを使用したチェックは、ローカルスコープ内のどこかで定義されている必要があります。そうでない場合、ローカルとは見なされません。

ローカルではなく、どこにも定義されていない変数の場合、チェックsomeVar === undefinedは例外をスローします:Uncaught ReferenceError:j is not defined

上記の内容を明確にするコードを以下に示します。 より明確にするためにインラインコメントに注意してください

function f (x) {
    if (x === undefined) console.log('x is undefined [x === undefined].');
    else console.log('x is not undefined [x === undefined.]');

    if (typeof(x) === 'undefined') console.log('x is undefined [typeof(x) === \'undefined\'].');
    else console.log('x is not undefined [typeof(x) === \'undefined\'].');

    // This will throw exception because what the hell is j? It is nowhere to be found.
    try
    {
        if (j === undefined) console.log('j is undefined [j === undefined].');
        else console.log('j is not undefined [j === undefined].');
    }
    catch(e){console.log('Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.');}

    // However this will not throw exception
    if (typeof j === 'undefined') console.log('j is undefined (typeof(x) === \'undefined\'). We can use this check even though j is nowhere to be found in our source code and it will not throw.');
    else console.log('j is not undefined [typeof(x) === \'undefined\'].');
};

上記のコードを次のように呼び出すと:

f();

出力は次のようになります。

x is undefined [x === undefined].
x is undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.

これらのような上記のコードを呼び出した場合(実際には任意の値で):

f(null); 
f(1);

出力は次のようになります。

x is not undefined [x === undefined].
x is not undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.

このようなチェックを行うときは、typeof x === 'undefined'、本質的にこれを尋ねています:ソースコードのどこかに変数xが存在する(定義されている)かどうかを確認してください (多かれ少なかれ)。 C#またはJavaを知っている場合、このタイプのチェックは実行されません。存在しない場合はコンパイルされないためです。

<== Fiddle Me ==>

1
CodingYoshi

typeof a === 'undefined'は、ノードv6.9.1でa === 'undefined'より約2倍高速です。

0
Eduard Popov