Comprendre la spécification ECMAScript, partie 2

Bonjour, Habr! Je présente à votre attention la traduction de l'article édité parxfides



Auteur original: Marja Hölttä

Traduction de la première partie.





Pratiquons-nous encore à lire les spécifications. Si vous n'avez pas vu l'article précédent, il est temps d'aller le regarder. Dans la première partie, nous nous sommes familiarisés avec la méthode simple Object.prototype.hasOwnProperty . Nous avons également examiné la liste des opérations abstraites qui sont appelées lorsque cette méthode est exécutée. Nous avons également appris les  abréviations spécifiques "?" et "!" liés à la gestion des erreurs. Enfin, nous avons obtenu des informations sur  les types de langage, les types de spécification, les emplacements internes et les méthodes internes.



Prêt pour la partie 2?



Avertissement! Cet épisode contient une copie des algorithmes de la spécification ECMAScript de février 2020. Naturellement, avec le temps, les informations deviendront obsolètes.



 ,   :   , ,     ,   ,   ,     . :



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



L'étape 1 évalue l'algorithme AssignmentExpression , qui est o2.foo . La référence contiendra le résultat du calcul.



À l'étape 2, nous appelons GetValue à partir de celui-ci. Ainsi, nous savons que la méthode interne de l'objet [[Get]] sera appelée et que le chaînage du prototype aura lieu.



Résumé



Dans cette partie, nous avons regardé comment la spécification définit les caractéristiques du langage; dans notre cas, une recherche prototype à travers toutes les différentes couches: des constructions syntaxiques qui exécutent des algorithmes et les étapes qui les définissent.




All Articles