Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose and arrow functions

I am hoping to clear up some of my confusion pertaining to arrow functions and lexical this, my use case with mongoose.

When adding a method to a mongoose Schema, one cannot use an arrow function. According to this article: https://hackernoon.com/javascript-es6-arrow-functions-and-lexical-this-f2a3e2a5e8c4 "Lexical Scoping just means that it uses this from the code that contains the Arrow Function."

So if I use an arrow function in a mongoose method, why does 'this' not refer to the schema object, whereas a pre-es6 function does? If the schema and arrow function are in the same file, is the lexical scope not bound to the schema?

Thank you!

UserSchema.methods.toJSON = function() {
  const user = this;
  const userObject = user.toObject();
  return _.pick(userObject, ['_id', 'email']);
};
like image 964
CoderXYZ Avatar asked May 08 '18 16:05

CoderXYZ


1 Answers

Lexical Scoping just means that it uses this from the code that contains the Arrow Function.

I'll just demonstrate it:

window.answer = 'Unknown'; // `this` equals to `window` in browser (no strict mode)
const object = {
  answer: 42,
  arrow: () => this.answer,
  wrap() {
    const arrow = () => this.answer;
    return arrow();
  },
  stillOuter() { return this.arrow();},
  method() {return this.answer;},
  likeArrow: function() {return this.answer;}.bind(this)
};

console.log(object.arrow(), object.stillOuter(), object.likeArrow()); // Unknown Unknown 
console.log(object.method(), object.wrap()); // 42 42

Arrow function's this just belongs to outer context.

So, if your arrow functions will be declared inside of correct object, this will be correct(almost) too.
Look into that workaround:

let tmp = Symbol(); // just to not interfere with something
UserSchema.methods[tmp] = function() {
  this.toJson = data => JSON.stringify(data);
  // All arrow functions here point into `UserSchema.methods` object
  // It will be still `UserSchema.methods` if implementation will copy these methods into other objects or call in the other context
};
UserSchema.methods[tmp]();
delete UserSchema.methods[tmp];
like image 56
vp_arth Avatar answered Sep 30 '22 13:09

vp_arth