Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a receiver in JavaScript?

Tags:

javascript

I am reading You Don't Know JS: ES6 & Beyond and found some confused wording like:

We declare a get(..) handler as a named method on the handler object (second argument to Proxy(..)), which receives a reference to the target object (obj), the key property name ("a"), and the self/receiver/proxy (pobj).

My question is, what does "receiver" mean above and where does its name come from?

It seems like if I have an object "a" with a member function "jump":

var a = { jump: function() { console.log('jump!'); } }; 

If I run a.jump(); then "a" is the receiver.

Is that how it works?

For people who read the same book: when you come to the Proxy First, Proxy Last section, you can add one line in the code to get a more clear picture about the context in the "get" trap:

var handlers = {     get(target, key, context) {         console.log(greeter === context); //true, this line added         return function() {             context.speak(key + "!");         };     } }, catchall = new Proxy({}, handlers), greeter = {     speak(who = "someone") {         console.log("hello", who);     } };  // setup `greeter` to fall back to `catchall` Object.setPrototypeOf(greeter, catchall);  greeter.speak();                // hello someone greeter.speak("world");       // hello world  greeter.everyone();             // hello everyone! 

As you can see, thanks to the naming of the third argument of the "get" trap above, "context", the receiver can vary according to lexical code -- greeter.everyone();. Please refer to Oriol's very detailed answer below for a better understanding.

like image 764
krave Avatar asked Jun 01 '16 08:06

krave


1 Answers

The receiver is the object in which the property lookup happens.

So yes, if you use a.jump, a is the receiver.

The concept is only relevant when you can execute arbitrary code when that property lookup happens. Basically, that means:

  • Accessor properties.

    You can access the receiver by using this inside the getter or setter. The receiver will usually be the object in which you defined the property, or another object which inherits from it.

    var target = {   get getReceiver() { return this; } }; target.getReceiver; // target var inherits = Object.create(target); inherits.getReceiver; // inherits 

    A built-in example is __proto__, defined as a property of Object.prototype but expected to be got or set on other objects (receivers).

  • Proxy objects

    Proxy objects allow you to define get or set traps, which run a function when you attempt to get or set any property to the proxy. The receiver is provided as an argument of that function. The receiver will usually the Proxy object itself, or an object which inherits from it.

    var proxy = new Proxy({}, {   get: function(target, property, receiver) {     return receiver;   } }); proxy.getReceiver; // proxy var inherits = Object.create(proxy); inherits.getReceiver; // inherits 

Note you can use Reflect.get or Reflect.set to specify arbitrary receivers:

Reflect.get(target, "getReceiver", arbitraryValue); // arbitraryValue ¹ Reflect.get(proxy, "getReceiver", arbitraryValue); // arbitraryValue 

¹ If the getter was defined in non-strict mode, it will be Object(arbitraryValue).

The name "receiver" comes from the specification, see Object Internal Methods and Internal Slots

  • [[Get]]   (propertyKey, Receiver) → any

    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.

  • [[Set]]   (propertyKey, value, Receiver) → Boolean

    Set the value of the property whose key is propertyKey to value. If any ECMAScript code must be executed to set the property value, Receiver is used as the this value when evaluating the code. Returns true if the property value was set or false if it could not be set.

like image 101
Oriol Avatar answered Oct 06 '22 01:10

Oriol