Halo, Habr! Untuk perhatian Anda saya persembahkan terjemahan dari artikel yang diedit olehxfides
Penulis asli: Terjemahan Marja Hölttä
dari bagian pertama.
Mari berlatih membaca spesifikasinya lagi. Jika Anda belum pernah melihat artikel sebelumnya, sekarang saatnya untuk menontonnya. Di bagian pertama, kita melihat metode Object.prototype.hasOwnProperty sederhana . Juga, kami melihat daftar operasi abstrak yang dipanggil saat metode ini dijalankan. Kami juga belajar tentang singkatan spesifik "?" dan "!" terkait dengan penanganan error. Akhirnya, kami mendapat informasi tentang jenis bahasa, jenis spesifikasi, slot internal, dan metode internal.
Siap untuk Bagian 2?
Peringatan! Episode ini berisi salinan algoritme dari spesifikasi ECMAScript Februari 2020. Secara alami, seiring berjalannya waktu, informasi tersebut akan menjadi usang.
, : , , , , , . :
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 , -.
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
7 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, , . , , , , .
Langkah 1 mengevaluasi algoritma AssignmentExpression , yaitu o2.foo . Ref akan berisi hasil perhitungan.
Pada langkah 2, kami memanggil GetValue darinya. Jadi, kita tahu bahwa metode internal dari objek [[Get]] akan dipanggil dan rangkaian prototipe akan berlangsung.
Ringkasan
Pada bagian ini, kita melihat bagaimana spesifikasi mendefinisikan fitur-fitur bahasa; dalam kasus kami, prototipe menelusuri semua lapisan yang berbeda: konstruksi sintaksis yang menjalankan algoritme dan langkah-langkah yang menentukannya.