[解決済み] なぜ0[0]は構文上有効なのですか?
疑問点
なぜこの行はjavascriptで有効なのでしょうか?
var a = 0[0];
その後に
a
は
undefined
.
どのように解決するのですか?
以下のような場合
0[0]
とすると、JSインタプリタが最初の
0
を
Number
オブジェクトを作成し、そのオブジェクトにアクセスします。
[0]
プロパティにアクセスします。
undefined
.
プロパティアクセスの構文である
0[0]
はこの文脈では言語文法で許可されているため、構文エラーは発生しません。 この構造(Javascriptの文法における用語を使用)は
NumericLiteral[NumericLiteral]
.
から言語文法の該当箇所を セクションA.3 の言語文法に関連する部分は、次のとおりです。
Literal ::
NullLiteral
BooleanLiteral
NumericLiteral
StringLiteral
RegularExpressionLiteral
PrimaryExpression :
this
Identifier
Literal
ArrayLiteral
ObjectLiteral
( Expression )
MemberExpression :
PrimaryExpression
FunctionExpression
MemberExpression [ Expression ]
MemberExpression . IdentifierName
new MemberExpression Arguments
というように、このような進行で文法を追っていくことができます。
MemberExpression [ Expression ]
PrimaryExpression [ Expression ]
Literal [ Expression ]
NumericLiteral [ Expression ]
また、同様に
Expression
も最終的には
NumericLiteral
にもなるので、文法に従った結果、これは許されることがわかります。
NumericLiteral [ NumericLiteral ]
ということは
0[0]
は文法上許される部分であり、したがってSyntaxErrorは発生しない。
次に、実行時に、存在しないプロパティを読み込むことが許可されます(それは単に
undefined
として読み込まれます)、読み込んでいるソースがオブジェクトであるか、オブジェクトへの暗黙の変換がある限り、存在しないプロパティを読み込むことが許可されます。 そして、数値リテラルは実際にオブジェクト(Numberオブジェクト)への暗黙の変換を持っています。
これは、Javascript のよく知られていない機能の 1 つです。 型は
Number
,
Boolean
と
String
は、通常プリミティブとして内部的に保存されます(本格的なオブジェクトではありません)。 これらは、コンパクトで不変のストレージ表現です(おそらく実装の効率化のためにこのようにしたのでしょう)。 しかし、Javascriptは、これらのプリミティブをプロパティやメソッドを持つオブジェクトのように扱えるようにしたいと考えています。 そのため、プリミティブで直接サポートされていないプロパティやメソッドにアクセスしようとすると、Javascriptは一時的にプリミティブを適切なオブジェクトの種類に強制変換し、その値をプリミティブの値として設定します。
プリミティブでオブジェクトのような構文、例えば
0[0]
のようなオブジェクトのような構文を使うと、 インタープリタはこれをプリミティブのプロパティアクセスとして認識します。 これに対する反応は、最初の
0
数値プリミティブを取り出し、それを本格的な
Number
オブジェクトにアクセスできるようにします。
[0]
プロパティにアクセスできるようになります。 この具体的な例では
[0]
プロパティは、Number オブジェクトに
undefined
であるため、この値は
0[0]
.
ここでは、プロパティを扱う目的で、プリミティブをオブジェクトに自動変換する記事を紹介します。
ECMAScript 5.1仕様の関連する部分を紹介します。
9.10 CheckObjectCoercible (オブジェクトの互換性)
値が以下の場合、TypeErrorをスローします。
undefined
または
null
を返し、それ以外の場合は
true
.
<イグ
- baseReference を MemberExpression の評価結果とします。
- baseValueをGetValue(baseReference)とする。
- propertyNameReferenceをExpressionの評価結果とします。
- propertyNameValueをGetValue(propertyNameReference)とする。
- CheckObjectCoercible(baseValue)を呼び出します。
- propertyNameStringをToString(propertyNameValue)とします。
- 評価されている構文生成物がストリクトモードのコードに含まれている場合、ストリクトをtrueとする。 モードのコードに含まれている場合、strict を true とし、そうでない場合は strict を false とします。
- 基本値がbaseValueで、参照名がpropertyNameStringであるReference型の値を返します。 参照される名前がpropertyNameStringであり、そのストリクトモードフラグが の値を返します。
この質問に対する操作部分は、上記のステップ#5です。
これは、アクセスされる値がプロパティ参照であるとき、どのように呼び出すかを記述しています。
ToObject(base)
で、任意のプリミティブのオブジェクトバージョンを取得することができます。
これは
Boolean
,
Number
と
String
プリミティブは、[[PrimitiveValue]]内部プロパティが適宜設定され、オブジェクト形式に変換されます。
面白いテストとして、もしコードがこのようなものであったなら。
var x = null;
var a = x[0];
これは技術的に合法な構文なのでパース時にSyntaxErrorは投げませんが、コードを実行したときにTypeErrorを投げます。
x
の値に適用されるとき、それは
CheckObjectCoercible(x)
を呼び出すか
ToObject(x)
を呼び出すと、どちらもTypeErrorを投げます。
x
が
null
または
undefined
.
関連
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] あるJavaScriptファイルを他のJavaScriptファイルにインクルードするにはどうすればよいですか?
-
[解決済み] JavaScript で配列に値が含まれているかどうかを確認するにはどうすればよいですか?
-
[解決済み] なぜGoogleはJSONレスポンスにwhile(1);を前置するのでしょうか?
-
[解決済み] 私のJavaScriptコードは "No 'Access-Control-Allow-Origin' header is present on requested resource "というエラーを受け取りますが、Postmanはそうならないのはなぜですか?
-
[解決済み] なぜ ++[[]][+[] +[+[]] は "10" という文字列を返すのでしょうか?
-
[解決済み】JavaScriptで文字列の出現箇所をすべて置換する方法
-
[解決済み】未定義のオブジェクトプロパティを検出する
-
[解決済み] ExtJS 4のイベントハンドリングについて
-
[解決済み] サブドメインにまたがってlocalStorageを使用する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] AngularJSのエラーです。Cross Origin リクエストはプロトコルスキーム http, data, chrome-extension, https に対してのみサポートされています。
-
[解決済み] モバイルWeb HTML5フレームワークの選び方【終了しました
-
[解決済み] 文字列が空白であるかどうかをチェックする
-
[解決済み] React js 親コンポーネントから子コンポーネントの状態を変更する
-
[解決済み] javascript includes() 大文字小文字を区別しない
-
[解決済み] react-routerのハッシュフラグメントからクエリパラメータを取得する
-
[解決済み] TypeScriptプロジェクトで既存のC#クラス定義を再利用する方法
-
[解決済み] JSHintの'+'前の改行不良の説明
-
[解決済み] なぜjavascriptのES6 Promisesはresolve後も実行を継続するのですか?
-
[解決済み] JavaScriptデータフォーマット/プリティプリンタ