この行がJavaScriptで有効なのはなぜですか?
var a = 0[0];
その後、aですundefined。
"0"、new Number(0)オブジェクトの名前付きプロパティを取得するだけです。
0[0]値を返すことは完全に可能です
0["toString"]それは素晴らしいです、指摘してくれてありがとう。
この行がJavaScriptで有効なのはなぜですか?
var a = 0[0];
その後、aですundefined。
"0"、new Number(0)オブジェクトの名前付きプロパティを取得するだけです。
0[0]値を返すことは完全に可能です
0["toString"]それは素晴らしいです、指摘してくれてありがとう。
回答:
あなたが行うと0[0]、JSインタプリタは最初に変わります0にNumber、オブジェクトとその後、アクセスしようと[0]しているオブジェクトのプロパティをundefined。
プロパティのアクセス構文0[0]は、このコンテキストの言語文法で許可されているため、構文エラーはありません。この構造(JavaScript文法の用語を使用)はNumericLiteral[NumericLiteral]です。
ES5 ECMAScript仕様のセクション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およびStringJavaScriptは通常、内部的にプリミティブとして格納されます(本格的なオブジェクトではありません)。これらは、コンパクトで不変のストレージ表現です(おそらく、実装効率のためにこの方法で行われます)。しかし、Javascriptでは、これらのプリミティブをプロパティやメソッドを持つオブジェクトのように扱えるようにしたいと考えています。そのため、プリミティブで直接サポートされていないプロパティまたはメソッドにアクセスしようとすると、JavaScriptは一時的にプリミティブを適切なタイプのオブジェクトに強制し、値をプリミティブの値に設定します。
などのプリミティブでオブジェクトのような構文を使用する0[0]と、インタプリタはこれをプリミティブのプロパティアクセスとして認識します。これに対するその応答は、最初の0数値プリミティブを取得してNumber、[0]プロパティにアクセスできる完全なオブジェクトに変換することです。この特定のケースでは[0]、Numberオブジェクトのプロパティがundefinedそのため、取得する値です0[0]。
プロパティを処理するためのプリミティブからオブジェクトへの自動変換に関する記事を次に示します。
ECMAScript 5.1仕様の関連部分は次のとおりです。
値がundefinedまたnullはの場合はTypeErrorをスローし、それ以外の場合はを返しますtrue。

- baseReferenceをMemberExpressionの評価結果とします。
- baseValueをGetValue(baseReference)とします。
- propertyNameReferenceを式の評価結果とします。
- propertyNameValueをGetValue(propertyNameReference)にします。
- CheckObjectCoercible(baseValue)を呼び出します。
- propertyNameStringをToString(propertyNameValue)にします。
- 評価される構文生成がstrictモードのコードに含まれている場合は、strictをtrue、それ以外の場合はstrictをfalseにします。
- 基本値がbaseValueであり、参照名がpropertyNameStringであり、strictモードフラグがstrictであるReferenceタイプの値を返します。
この質問の有効な部分は、上記のステップ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。
0[1,2]も有効ですが、どういう意味ですか?(質問を更新します)
nullやundefinedまったく問題がない場合でもプロパティにアクセスできるため、構文エラーは発生しません。
0[2]
1,2ますが、2を返します
ほとんどのプログラミング言語と同様に、JSは文法を使用してコードを解析し、実行可能な形式に変換します。文法に、特定のコードチャンクに適用できるルールがない場合、SyntaxErrorがスローされます。それ以外の場合、コードは意味があるかどうかにかかわらず、有効であると見なされます。
JS文法の関連部分は
Literal ::
NumericLiteral
...
PrimaryExpression :
Literal
...
MemberExpression :
PrimaryExpression
MemberExpression [ Expression ]
...
0[0]これらのルールに準拠しているため、有効な式と見なされます。それが正しいかどうか(実行時にエラーをスローしないなど)は別の話ですが、そうです。これは、JSが次のような式を評価する方法ですsomeLiteral[someExpression]。
someExpression(これは任意の複雑な場合があります)Number、文字列=> Stringなど)get propertyプロパティ名result(1)でresult(2)の操作を呼び出しますしたがって0[0]、次のように解釈されます
index = 0
temp = Number(0)
result = getproperty(temp, index) // it's undefined, but JS doesn't care
delete temp
return result
有効であるが正しくない式の例を次に示します。
null[0]
正常に解析されますが、実行時にステップ2でインタープリターが失敗し(nullオブジェクトに変換できないため)、ランタイムエラーがスローされます。
var x = null; var a = x[0];構文エラーは生成しませんが、実行時にTypeErrorをスローします。
0[0]未定義の代わりに値を返すことは可能です
Javascriptで数値に有効に添字を付けることができる状況があります。
-> 0['toString']
function toString() { [native code] }
なぜこれを実行するのかはすぐにはわかりませんが、JavaScriptでの添え字付けは、ドット表記法を使用することと同じです(ただし、ドット表記法はキーとしての識別子の使用に制限されます)。
(0).toString(関数を呼び出さずに)と同じです。数値型のプロパティです。
0プロパティがアクセスされ、それが存在しないためには、undefinedあるより jfriend00で説明したように正しいです。
0[0]は未定義を返す誤った仮定です。可能性は高いですが、そうである必要はありません
これは有効な構文であり、JavaScriptに固有のものではないことに注意してください。ほとんどの言語には実行時エラーまたは型エラーがありますが、それは構文エラーと同じではありません。Javascriptは、指定された名前のプロパティを持たないオブジェクトに添え字を付ける場合など、別の言語が例外を発生させる可能性のある多くの状況で未定義を返すことを選択します。
構文は式のタイプ(数値リテラルのような単純な式でさえ)を知らないため、任意の演算子を任意の式に適用できます。たとえば、Javascriptで添え字を付けようとしundefinedたり、null引き起こしたりTypeErrorします。これは構文エラーではありません-これが決して実行されない場合(ifステートメントの間違った側にある場合)は、問題は発生しませんが、構文エラーは定義上、常にコンパイル時にキャッチされます(eval、Functionなど)。 、すべてコンパイルとしてカウントされます)。
構文が有効であるだけでなくundefined、ほとんどすべての場合ではなくても、ほとんどの場合、結果はそうである必要はありません。JSは、最も純粋なオブジェクト指向言語の1つです。ほとんどのいわゆるOO言語はクラス指向であり、一度作成されたオブジェクトの形式(クラスに関連付けられている)を変更することはできず、オブジェクトの状態のみを変更することができます。JSでは、オブジェクトの状態とフォームを変更できますが、これは思ったより頻繁に行うことができます。この機能は、コードを誤用した場合に、かなりあいまいなコードになります。数値は不変であるため、オブジェクト自体を変更することはできません。状態やフォームではないため、変更できます
0[0] = 1;
これは、1を返すが実際には何も割り当てない有効な割り当て式です0。数値は不変です。それ自体は少し奇妙です。何も割り当てない有効で正しい(実行可能な)割り当て式を使用できます(*)。ただし、数値のタイプは変更可能なオブジェクトであるため、タイプを変更でき、変更はプロトタイプチェーンにカスケードされます。
Number[0] = 1;
//print 1 to the console
console.log(0[0]);
//will also print 1 to the console because all integers have the same type
console.log(1[0]);
もちろんそれはまともな使用カテゴリからは程遠いですが、他のシナリオではオブジェクトの機能を拡張することは実際には非常に理にかなっているため、言語はこれを可能にするように指定されています。これは、jQueryプラグインがjQueryオブジェクトにフックして例を示す方法です。
(*)実際には値1をオブジェクトのプロパティに割り当てますが、その(一時的な)オブジェクトを参照する方法はないため、nexx GCパスで収集されます
JavaScriptでは、すべてがオブジェクトであるため、インタープリターはそれを解析するときに、0をオブジェクトとして扱い、0をプロパティとして返そうとします。trueまたは ""(空の文字列)の0番目の要素にアクセスしようとすると、同じことが起こります。
0 [0] = 1を設定しても、プロパティとその値はメモリに設定されますが、0にアクセスしている間は数値として扱われます(ここでは、オブジェクトと数値の扱いを混同しないでください)。
true[0]または""[0]