※ ChatGPTを利用し、要約された質問です(原文:obj.property のundefined判定)
JavaScriptでの未定義のプロパティの評価方法と仕様書の解釈について
このQ&Aのポイント
JavaScriptにおいて、未定義のローカル変数を評価する際にはtypeofを使用する必要がある。
一方、存在が保証されているオブジェクトの存在しないプロパティを評価する場合は、obj.propertyがnullなためundefinedを返す。
ECMA-262 3rd Edition仕様書の解釈によれば、このような処理が行われることが確認できる。
obj.property のundefined判定
obj.property のundefined判定
未定義のローカル変数を評価すると、以下の結果になります。
<script type="text/javascript"><!--
var a;
if(a === undefined){ alert('a is undefined!'); } // エラーは発生しない
if(b === undefined){ alert('b is undefined!'); } // 「ReferenceError: b is not defined」のエラーが発生し、if文が評価されない
if('undefined' === typeof b){ alert('b is undefined!'); } // エラーは発生しない
//--></script>
未定義のローカル変数は undefined との比較ではチェックできず、typeof でチェックする必要があることが分かります。
対して、「存在が保証されているオブジェクトの存在しないプロパティ」でチェックすると、以下の結果になります。
<script type="text/javascript"><!--
var obj = { a:'valueA', b:'valueB' };
if(obj.property === undefined){ alert('obj.property is undefined!'); } // エラーは発生しない
if('undefined' === typeof obj.property){ alert('obj.property is undefined!'); } // エラーは発生しない
//--></script>
不思議に思い、ECMA-262 3rd Edition仕様書を読んでみたところ、下記文言が見つかりました。
----------
8.6.2.1 [[Get]] (P)
O の [[Get]] メソッドがプロパティ名 P で呼出されると、次のステップがとられる:
1. O が P という名前のプロパティを持っていなければ、ステップ 4 へ進む。
2. そのプロパティの値を取得する。
3. Result(2) を返す。
4. O の [[Prototype]] が null ならば、undefined を返す。
5. [[Prototype]] の [[Get]] メソッドを、プロパティ名 P で呼び出す。
6. Result(5) を返す。
http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/8_Types.html#section-8.6.2
----------
この場合、ステップ4の「obj.property が nullなため undefined を返す」という処理が行われた、という解釈で合っているでしょうか?
ほぼ正しいと感じているのですが、「仕様書の中で見るべきところが合っているのか」に自信が持てず、確信に至っていません…。
お礼
改めて読み直して、頭を抱えました…。 「obj.prototype がnullならば、undefined を返す」と書きたかったはずなのにw fujillinさんが回答された内容は、私の理解と一致しています。 とりあえず、「問題ない」ってことなのかな? しばらく待って、新しい回答がつかなければ締め切りたいと思います。 ありがとうございます。 > プロパティの有無は、 property in object でも判別可能みたい。 babu_babooさんが同じような回答をされていましたね。 hasOwnProperty() は存在しないプロパティを評価したら、false を返し、 in演算子は存在しないプロパティを評価したら、false を返す、ということは分かりました。 (in演算子はちょっと分かりづらいですが、最終的には [[HasProperty]]メソッドを呼び出して、true, false を返しています。) hasOwnProperty - MDC https://developer.mozilla.org/ja/Core_JavaScript_1.5_Reference/Global_Objects/Object/hasOwnProperty 11.8.7 in 演算子 (The in operat - 11 式 (Expressions) http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/11_Expressions.html#section-11.8.7 8.7.1 GetValue (V) - 8 型 (Types) http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/8_Types.html#section-8.7.1 8.6.2.4 [[HasProperty]] (P) - 8 型 (Types) http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/8_Types.html#section-8.6.2.4 今回、私が疑問に感じたのは「obj.property を評価するときに、なぜ "ReferenceError: obj.property is not defined" にならないのか?」というものです。 未定義のローカル変数では ReferenceError が返るので、直感的に「未定義のプロパティ参照も ReferenceError になるはずだ」と思ってしまったんです。 だから、「プロパティ評価は、typeof演算子ないしhasOwnProperty() メソッドを使用した方が無難」と今までは考えていたのですが、どうも undefined との比較でも通ってしまうようなので「実際のところはどうすべきなのだろう?」と思いまして。
補足
すみません…、自己解決しました。(汗) 「プロパティアクセス演算子」で obj.property の評価についての解説があり、最終的にはやはり [[Get]]メソッド を使用していました。 11.2.1 プロパティアクセス演算子 - 11 式 (Expressions) http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/11_Expressions.html#section-11.2.1 8.7.1 GetValue (V) - 8 型 (Types) http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/8_Types.html#section-8.7.1 8.6.2.1 [[Get]] (P) - 8 型 (Types) http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/8_Types.html#section-8.6.2.1 検証頂き、ありがとうございました。