2

I was trying to implement mongoose virtual getter :

   UserSchema.virtual('fullName')
   .get(function () {
    return `${this.firstName} ${this.lastName}`;
})

I have noticed that when I use es6 arrow function instead of the normal anonymous function as a parameter to the the get the virtual getter would return undefined.

I know that arrow functions keeps the context of this but where is the this that the normal anonymous function is using?. if it was passed by .bind or using the call()/apply() functions then it shouldn't matter if it is arrow function or normal(that's what I tested atleast). So why is this only working with normal functions but not arrow functions?.

  • Yes, I know. But this arrow function does not work. The one I typed is the one that works. And why does that happen is my question. – Abdurrahman Jun 02 '17 at 13:25
  • Gotcha. Off the top of my head it's about applying to the model instance, but I suppose a full explanation would be nice. – Neil Lunn Jun 02 '17 at 13:28

3 Answers3

0

The this that the normal anonymous function is using is being provided by get().

If you use an arrow function, you are binding this yourself, which means it's bound to the this in your function that calls get().

You would see the same thing happen if you called

.get((function() {
    return `${this.firstName} ${this.lastName}`;
}).bind(this))
Jacob Krall
  • 25,736
  • 6
  • 59
  • 74
0

I know that arrow functions keeps the context of this

They do. It is like using function () { ... }.bind(this).

but where is the this that the normal anonymous function is using?

It depends on how the function is called.

That is done by some other code deep inside the get function which you aren't currently looking at.

Since the function clearly makes use of this, that context matters.

if it was passed by .bind

… then you'd have the same problem as the arrow functions.

or using the call()/apply() functions

… then it would be called immediately rather than when you need it to be called.

then it shouldn't matter if it is arrow function or normal

It would matter. See above.

Quentin
  • 800,325
  • 104
  • 1,079
  • 1,205
0

Arrow function has a special binding for this that is coming from its lexical context.

if it was passed by .bind or using the call()/apply() functions then it shouldn't matter if it is arrow function or normal(that's what I tested atleast).

I tested it myself and the arrow function take precedence over call:

function f () { var f = () => console.log(this.a); f.call({a: 2});}
f.call({a: 3})
> 3

The logic behind this behavior probably could be understood from this quote from the spec:

An ArrowFunction does not define local bindings for arguments, super, this, or new.target. Any reference to arguments, super, this, or new.target within an ArrowFunction must resolve to a binding in a lexically enclosing environment.

If arrow function does not have its own binding for this then bind/call/apply/etc. have no effect on its this binding.

amiramw
  • 501
  • 2
  • 10