Both "receiver" and "target" are used in the ES2015 spec (see examples below) and elsewhere on the Web, to refer to the object used as the this
value.
Are these words synonyms or do they have subtly different meanings?
Is there a single correct term to refer to the this
value of a function at invocation time?
I note that the signature of Reflect.get
in 26.1.6 uses both terms indicating a difference of meaning.
This question stems from a perceived inconsistency of nomenclature in the ES2015 spec.
Spec Usage Examples:
Table 5, row 7 ([[Get]]
), section 6.1.7.2 (my emboldening):
Return the value of the property whose key is propertyKey from this object. If any ECMAScript code must be executed to retrieve the property value, Receiver is used as the this value when evaluating the code.
Paragraph 2, section 6.1.7.2 (my emboldening):
Internal method names are polymorphic. This means that different object values may perform different algorithms when a common internal method name is invoked upon them. That actual object upon which an internal method is invoked is the “target” of the invocation. If, at runtime, the implementation of an algorithm attempts to use an internal method of an object that the object does not support, a TypeError exception is thrown.
1 Answers
Answers 1
To recap:
Every call to the internal method of an object has a "target", the object which the call is made on.
"Receiver" is the 2nd parameter of the
[[Get]]
method, and the 3rd of the[[Set]]
method.Other internal object methods don't have this extra parameter.
Then, why does [[Get]]
and [[Set]]
have Receiver? Because it is not target.
Receiver is used to call getter and setter in the scope of [[Get]] / [[Set]].
ES6 9.1.8:
- You call
A.Get( 'property', A )
- If A does not have 'property',
A.prototype.Get( 'property', A )
is called.- Target is now "A.prototype". But Receiver remains "A".
- If A.prototype has a getter function for 'property', it will be called with Receiver A, instead of the target A.prototype.
Note that ES5's [[Get]] (8.12.3) do the same in a different way and without Receiver, partially because prototype climbing happens in another part (8.12.2).
Receiver only exist in the context of [[Get]] and [[Set]], and serves a different purpose than target.
When [[Get]] need to refer its target, it use O.
O is different for each recursive call of [[Get]] as it climbs the prototype chain.Receiver remains the same as [[Get]] climbs the prototype chain. Its value is passed to getter as a parameter, and what happens next is no longer in the same scope as Receiver.
O and Receiver may refer to the same object, but that doesn't matter in the context of [[Get]] or [[Set]]. In fact, Reflect.get allows the caller to set a different target and Receiver and make them different from the get go.
For other internal object methods, most of them do not climb the prototype chain at all. The two that do ([[HasProperty]]
and [[Enumerate]]
), don't need to preserve the initial target (so to speak).
With that settled, you then ask whether the spec gives "Receiver" a meaning to be used in general JavaScript discussion, like how it defines "target" in 6.1.7.2. This answer is no.
"Receiver" has a very narrow scope, used only as parameter name, but "target" is used there in a general, less formal way.
"target" is a term borrowed from general discussions - ES 5 doesn't have the concept of target of invocation. In ES5, target is either a parameter or the
this
value.The spec is written to convey "JavaScript behaviour" in very, very precise terms, making it very technical including the use of parameter. It simply serves a different communication than general technical discussions.
3.a. Many JS developer does not read the spec at all. It is unnecessary for everyday use.
3.b. We talk about "closure", "scope chains", "event queue", and "fat arrow" or "lambda", do we not? The spec defined none of these terms.
3.c. The spec may call things differently, as in Execution Context or Job Queue.
It may simply not name things. Closure is an emergent behaviour.
And when it does name, it does not create alias. Arrow Function is never called lambda.
The spec does not regulate general discussions.
Use common sense for common discussions.
0 comments:
Post a Comment