Comprensión de la especificación ECMAScript, Parte 2

¡Hola, Habr! Les presento a su atención la traducción del artículo editado porxfides



Autor original: Marja Hölttä

Traducción de la primera parte.





Practiquemos la lectura de la especificación un poco más. Si no ha visto el artículo anterior, es hora de ir a verlo. En la primera parte, vimos el método Object.prototype.hasOwnProperty simple . Además, miramos la lista de operaciones abstractas que se llaman cuando se ejecuta este método. También aprendimos sobre las  abreviaturas específicas "?" y "!" relacionados con el manejo de errores. Finalmente, obtuvimos información sobre  tipos de lenguaje, tipos de especificación, espacios internos y métodos internos.



¿Listo para la Parte 2?



¡Advertencia! Este episodio contiene una copia de los algoritmos de la especificación ECMAScript de febrero de 2020. Naturalmente, con el tiempo, la información quedará obsoleta.



 ,   :   , ,     ,   ,   ,     . :



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,    , . , ,  , ,    .



El paso 1 evalúa el algoritmo AssignmentExpression , que es o2.foo . La referencia contendrá el resultado del cálculo.



En el paso 2, llamamos GetValue desde allí. Por lo tanto, sabemos que se llamará al método interno del objeto [[Get]] y se llevará a cabo el encadenamiento del prototipo.



Resumen



En esta parte, analizamos cómo la especificación define las características del lenguaje; en nuestro caso, un prototipo de búsqueda a través de las diferentes capas: construcciones sintácticas que ejecutan algoritmos y los pasos que los definen.




All Articles