Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are "target" and "receiver" synonyms in the ES2015 specification?

Tags:

javascript

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.

like image 581
Ben Aston Avatar asked Jun 05 '16 17:06

Ben Aston


2 Answers

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:

  1. You call A.Get( 'property', A )
  2. If A does not have 'property', A.prototype.Get( 'property', A ) is called.
    1. Target is now "A.prototype". But Receiver remains "A".
    2. 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.

  1. "Receiver" has a very narrow scope, used only as parameter name, but "target" is used there in a general, less formal way.

  2. "target" is a term borrowed from general discussions - ES5 doesn't define the concept of target of invocation. ES5 "target" can be a parameter, variable, statement, expression, or the called function. But not an implicit replacement for this.

  3. 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 programming discussions.

    3.a. Many JS developer don't read the spec at all. It is unnecessary for everyday coding.

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

like image 128
Sheepy Avatar answered Oct 19 '22 02:10

Sheepy


This probably does not answer the question. But here goes..

The term receiver derives from OOP design where everything is abstracted as objects. Execution of a program consists mainly of communication between objects. Object communicate with each other by invoking each other's methods. Thus the object being invoked upon is receiving a message. Hence the term.

The syntax, however, has extended to languages/contexts where there are, in a sense, "objects" but not exactly OOP. Many languages pick up the convenience of being able to invoke a function/method via some object/scope using the syntax some_object.some_method() and still refer to some_object as being the receiver. Usually referred to as this or self or just first parameter or a combination thereof in the function/method definition. JavaScript takes this a step further and allows dynamic binding of this. While in fact the object being called upon is not receiving anything and the syntax is just sugar for implicitly using the object as one of the arguments to the function being invoked.

like image 1
joegomain Avatar answered Oct 19 '22 02:10

joegomain