哈Ha!敬请注意,我翻译了xfides
让我们练习阅读更多规范。如果您还没有看过上一篇文章,那么该看一下了。在第一部分中,我们看到了简单的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 , -.
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, , . , , , , .
步骤1评估了AssignmentExpression算法,该算法为o2.foo。引用将包含计算结果。
在步骤2中,我们从中调用GetValue。因此,我们知道将调用[[Get]]对象的内部方法,并且将进行原型链接。
概要
在这一部分中,我们研究了规范如何定义语言的功能。在我们的案例中,原型搜索了所有不同的层:运行算法的语法结构以及定义它们的步骤。