为什么0 [0]语法上有效? [英] Why is 0[0] syntactically valid?

查看:139
本文介绍了为什么0 [0]语法上有效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么这条线在javascript中有效?

  var a = 0 [0]; 

之后, a undefined

解决方案

当你做 0 [0] ,JS解释器将第一个 0 转换为 Number 对象,然后尝试访问该对象的 [0] 属性, undefined



没有语法错误,因为在此上下文中语言语法允许使用属性访问语法 0 [0] 。此结构(使用Javascript语法中的术语)是 NumericLiteral [NumericLiteral]



该语言的相关部分来自ES5 ECMAScript的



  1. 让baseReference成为评估MemberExpression的结果。

  2. 让baseValue为GetValue(baseReference)。

  3. 让propertyNameReference成为评估Expression的结果。

  4. 让propertyNameValue为GetValue(propertyNameReference)。

  5. 调用CheckObjectCoercible(baseValue)。

  6. 让propertyNameString为ToString(propertyNameValue)。

  7. 如果正在评估的语法生成包含在严格的
    模式代码中,则let strict为true,否则let strict为false。

  8. 返回类型为Reference的值,其基值为baseValue,其
    引用的名称为propertyNameString,其严格模式标志为
    strict。


此问题的执行部分是上面的第5步。



8.7.1 GetValue(V)



这描述了当被访问的值是属性引用时,它调用 ToObject(base)来获取任何原语的对象版本。



9.9 ToObject



这描述了 Boolean 的方式数字字符串基元转换为对象形式,相应地设置了[[PrimitiveValue]]内部属性。






作为一个有趣的测试,如果代码是这样的:

  var x = null; 
var a = x [0];

它仍然不会在解析时抛出一个SyntaxError,因为这是技术上合法的语法,但它会抛出运行代码时运行时出现TypeError,因为当上面的Property Accessors逻辑应用于 x 的值时,它将调用 CheckObjectCoercible(x) 或调用 ToObject(x)如果 x <$ c,则会抛出TypeError c $ c> null 或 undefined


Why is this line valid in javascript ?

var a = 0[0];

After that, a is undefined.

解决方案

When you do 0[0], the JS interpreter will turn the first 0 into a Number object and then try to access the [0] property of that object which is undefined.

There is no syntax error because the property access syntax 0[0] is allowed by the language grammar in this context. This structure (using terms in the Javascript grammar) is NumericLiteral[NumericLiteral].

The relevant part of the language grammar from section A.3 of the ES5 ECMAScript spec is this:

Literal ::
    NullLiteral
    BooleanLiteral
    NumericLiteral
    StringLiteral
    RegularExpressionLiteral

PrimaryExpression :
    this
    Identifier
    Literal
    ArrayLiteral
    ObjectLiteral
    ( Expression )

MemberExpression :
    PrimaryExpression
    FunctionExpression
    MemberExpression [ Expression ]
    MemberExpression . IdentifierName
    new MemberExpression Arguments    

So, one can follow the grammer through this progression:

MemberExpression [ Expression ]
PrimaryExpression [ Expression ]
Literal [ Expression ]
NumericLiteral [ Expression ]

And, similarly Expression can also eventually be NumericLiteral so after following the grammar, we see that this is allowed:

NumericLiteral [ NumericLiteral ]

Which means that 0[0] is an allowed part of the grammar and thus no SyntaxError.


Then, at run-time you are allowed to read a property that does not exist (it will just be read as undefined) as long as the source you are reading from either is an object or has an implicit conversion to an object. And, a numeric literal does indeed have an implicit conversion to an object (a Number object).

This is one of those often unknown features of Javascript. The types Number, Boolean and String in Javascript are usually stored internally as primitives (not full-blown objects). These are a compact, immutable storage representation (probably done this way for implementation efficiency). But, Javascript wants you to be able to treat these primitives like objects with properties and methods. So, if you try to access a property or method that is not directly supported on the primitive, then Javascript will temporarily coerce the primitive into an appropriate type of object with the value set to the value of the primitive.

When you use an object-like syntax on a primitive such as 0[0], the interpreter recognizes this as a property access on a primitive. Its response to this is to take the first 0 numeric primitive and coerce it into a full-blown Number object which it can then access the [0] property on. In this specific case, the [0] property on a Number object is undefined which is why that's the value you get from 0[0].

Here is an article on the auto-conversion of a primitive to an object for purposes of dealing with properties:

The Secret Life of Javascript Primitives


Here are the relevant portions of the ECMAScript 5.1 specification:

9.10 CheckObjectCoercible

Throws TypeError if value is undefined or null, otherwise returns true.

11.2.1 Property Accessors

  1. Let baseReference be the result of evaluating MemberExpression.
  2. Let baseValue be GetValue(baseReference).
  3. Let propertyNameReference be the result of evaluating Expression.
  4. Let propertyNameValue be GetValue(propertyNameReference).
  5. Call CheckObjectCoercible(baseValue).
  6. Let propertyNameString be ToString(propertyNameValue).
  7. If the syntactic production that is being evaluated is contained in strict mode code, let strict be true, else let strict be false.
  8. Return a value of type Reference whose base value is baseValue and whose referenced name is propertyNameString, and whose strict mode flag is strict.

An operative part for this question is step #5 above.

8.7.1 GetValue (V)

This describes how when the value being accessed is a property reference, it calls ToObject(base) to get the object version of any primitive.

9.9 ToObject

This describes how Boolean, Number and String primitives are converted to an object form with the [[PrimitiveValue]] internal property set accordingly.


As an interesting test, if the code was like this:

var x = null;
var a = x[0];

It would still not throw a SyntaxError at parse time as this is technically legal syntax, but it would throw a TypeError at runtime when you run the code because when the above Property Accessors logic is applied to the value of x, it will call CheckObjectCoercible(x) or call ToObject(x) which will both throw a TypeError if x is null or undefined.

这篇关于为什么0 [0]语法上有效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆