了解ECMAScript规范,第2部分

哈Ha!敬请注意,我翻译了xfides



原作者:MarjaHölttä

第一部分的翻译。





让我们练习阅读更多规范。如果您还没有看过上一篇文章,那么该看一下了。在第一部分中,我们看到了简单的Object.prototype.hasOwnProperty方法另外,我们查看了执行此方法时调用抽象操作的列表我们还了解了 具体的缩写“?”。“!” 与错误处理有关。最后,我们获得了有关 语言类型,规范类型,内部插槽和内部方法的信息。



准备参加第2部分吗?



警告!本集包含2020年2月ECMAScript规范的算法副本。自然,随着时间的流逝,信息将变得过时。



我们知道,属性是沿着原型链搜索的:如果一个对象没有我们要读取的属性,我们将爬上原型链,直到找到它,或者找到一个没有自己原型的对象为止。例如:



const o1 = { foo: 99 };
const o2 = {};
Object.setPrototypeOf(o2, o1);
o2.foo;
// → 99


沿着原型链行走的算法在哪里定义?



让我们尝试查找此行为的定义位置。一个好的开始是从对象内部方法的列表开始



[[GetOwnProperty]] [[Get]]. ,    — [[Get]].  ,   [[Get]], , , ,    .



[[Get]] . ( )   . [[Get]],    .       .



[[Get]] ( P, Receiver ). OrdinaryGet. , [[Get]]   «»   «»  ECMAScript Receiver, :



    1. Return ? OrdinaryGet(O, P, Receiver).


 , Receiver — , this , -.



OrdinaryGet(O, P, Receiver) :



1.  Assert: IsPropertyKey(P) is true.
2.  Let desc be ? O.[[GetOwnProperty]](P).
3.  If desc is undefined, then
        a. Let parent be ? O.[[GetPrototypeOf]]().
        b. If parent is null, return undefined.
        c. Return ? parent.[[Get]](P, Receiver).
4.  If IsDataDescriptor(desc) is true, return desc.[[Value]].
5.  Assert: IsAccessorDescriptor(desc) is true.
6.  Let getter be desc.[[Get]].
7.  If getter is undefined, return undefined.
8.  Return ? Call(getter, Receiver).


:    ,   [[Get]] , OrdinaryGet.     ,   [[Get]] ,   OrdinaryGet.   ,    ,     null.



, ,   o2.foo.   OrdinaryGet     «» «2»,    «» — «foo». , O.[[GetOwnProperty]](«foo») undefined,     if   3, «o2»   «foo».



  3.a,     «parent»   «o2» — «o1». «parent» null,    if   3.b.



  3.   [[Get]]   «foo»   . «o1» — ,   [[Get]] OrdinaryGet .   ,   «» «1»,   «» «foo».



  2  O.[[GetOwnProperty]](«foo»)   ,      desc.



 — .   [[Value]].   [[Get]] / [[Set]].   ,  «foo» — .



 ,   desc   2,    if   3.



  4. ,  99,   [[Value]]   4.    .



Receiver    ?



Receiver   -   8.   this, -.



OrdinaryGet Receiver ( 3.c). , Receiver.



 , [[Get]], GetValue,  Reference. Reference — , ,   strict.   o2.foo «o2»,  — «foo»,   strict — false.



: Reference   Record?



Reference   Record,   .   ,   .   , Reference   Record   .



 GetValue.



, GetValue ( V ) :



1.  ReturnIfAbrupt(V).
2.  If Type(V) is not Reference, return V.
3.  Let base be GetBase(V).
4.  If IsUnresolvableReference(V) is true, throw a ReferenceError exception.
5.  If IsPropertyReference(V) is true, then
     .If HasPrimitiveBase(V) is true, then
         i.Assert: In this case, base will never be undefined or null.
         ii.Set base to ! ToObject(base).
     b.Return ? base.[[Get]](GetReferencedName(V),   GetThisValue(V)).
6.  Else,
      a.Assert: base is an Environment Record.
      b.Return ? base.GetBindingValue(GetReferencedName(V), IsStrictReference(V))


Reference   o2.foo, property reference.



,    if   5.     5.a, «2»   (, , , BigInt, Boolean, Undefined, Null).



  [[Get]]   5.b. Receiver,   — , GetThisValue(V).   GetThisValue( V ) Reference:



1.  Assert: IsPropertyReference(V) is true.
2.  If IsSuperReference(V) is true, then
        a.Return the value of the thisValue component of the reference V.
3.  Return GetBase(V).


o2.foo,    if   2, o2.foo   Super Reference( super.foo), , 3   Reference, «o2».



,  ,   Receiver Reference, , ,       . ,  , ,  , -,   Receiver this.



  , this   ,   ,    ,       .



!



const o1 = { x: 10, get foo() { return this.x; } };
const o2 = { x: 50 };
Object.setPrototypeOf(o2, o1);
o2.foo;
// → 50


    - «foo»,    . «this.x.».



  o2.foo — ?



 , ,   , this ,     ,   ,     .   , this «2»,    «1».     , , : o2.x o1.x.     o2.x.



, !     ,    .



 —  — [[Get]]?



  , [[Get]] ,   o2.foo? , - .    !



 , [[Get]]   GetValue,  References.   GetValue?



  MemberExpression



.   ,  , .



      - ,   .



    ,   .  ,   (Yield, Await  ..)     .



, MemberExpression :



MemberExpression :
     PrimaryExpression
     MemberExpression [ Expression ]
     MemberExpression . IdentifierName
     MemberExpression TemplateLiteral
     SuperProperty
     MetaProperty
     new MemberExpression Arguments


MemberExpression.



MemberExpression PrimaryExpression. MemberExpression   MemberExpression Expression, : MemberExpression[Expression], o2[’foo’].   MemberExpression.IdentifierName, o2.foo — .



  Runtime Semantics: Evaluation for MemberExpression: MemberExpression. IdentifierName :



1.  Let baseReference be the result of evaluating MemberExpression.
2.  Let baseValue be ? GetValue(baseReference).
3.  If the code matched by this MemberExpression is strict mode code, let strict be true; else let strict be false.
4.  Return ? EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict).


  EvaluatePropertyAccessWithIdentifierKey,    . EvaluatePropertyAccessWithIdentifierKey(baseValue, identifierName, strict)   baseValue, identifierName,   strict   :



1.  Assert: identifierName is an IdentifierName
2.  Let bv be ? RequireObjectCoercible(baseValue).
3.  Let propertyNameString be StringValue of identifierName.
4.  Return a value of type Reference whose base value component is bv, whose referenced name component is propertyNameString, and whose strict reference flag is strict.


, EvaluatePropertyAccessWithIdentifierKey Reference, baseValue   base, identifierName ,  strict .



 , Reference GetValue.    ,    , Reference   .



MemberExpression



    :



console.log(o2.foo);


  , ArgumentList: AssignmentExpression.  ,   .   GetValue :



Runtime Semantics: ArgumentListEvaluation



1.  Let ref be the result of evaluating AssignmentExpression.
2.  Let arg be ? GetValue(ref).
3.  Return a List whose sole item is arg.


o2.foo   AssignmentExpression,    , . , ,  , ,    .



步骤1评估了AssignmentExpression算法,该算法o2.foo引用将包含计算结果。



在步骤2中,我们从中调用GetValue因此,我们知道将调用[[Get]]对象的内部方法,并且将进行原型链接。



概要



在这一部分中,我们研究了规范如何定义语言的功能。在我们的案例中,原型搜索了所有不同的层:运行算法的语法结构以及定义它们的步骤。




All Articles