-3

I was racking my brain to make an algorithm in nodeJS work. I got a file with that function bellow where some properties are tied to this and some functions are tied to prototype.

function Main(controller) {
        this.tipo = "string";
        this.controller = controller;
        this.debug = controller.debug;
        this.db = controller.db;
        this.util = require('util');
        this.utils = require('../utils.js');
        this.moment = require('moment');
}

Main.prototype.funcX = (dados) => {
        // doing stuffs
}

Somehow, the properties of this were not being recognized in functions tied to prototype and there was always an TypeError.

Then, I've found a solution after reading this question, where I noticed that arrow function has its own this context. Then, changing this code snippet

Main.prototype.funcX = (dados) => {
    // doing stuffs
    console.log(typeof this.db) // TypeError: cannot read property 'info' of undefined
};

To this

 Main.prototype.funcX = function (dados) {
     // doing stuffs 
     console.log(typeof this.db) // prints my db instance
 };

made everything works well.

But I do not want to use function keyword to these functions at all.

Q: What is the best way to use arrow functions accessing the Main's this properties?

Atomzwieback
  • 528
  • 7
  • 14
Taylon Assis
  • 192
  • 2
  • 16
  • 3
    you should **not** use arrow function for this. – apple apple Dec 13 '18 at 13:05
  • 1
    Use a normal function. That's not how arrow functions work. Or just define a class instead of using the old-style constructor function. – Jared Smith Dec 13 '18 at 13:05
  • 2
    I think you misunderstand the whole point of arrow functions - please read some documentation and you'll see that arrow functions are not a replacement for "regular" `function`s - just like a screwdriver is not a replacement for a hammer - the right tool for the job – Jaromanda X Dec 13 '18 at 13:05
  • 1
    I think it's actually correct to throw the error, since the function's "this" is not the Main prototype, but it's parent. To solve the issue, what about using the ES6 Class declarations? You are already using ES6 since you're targeting arrow functions, so I don't exactly see the point to use a prototype in your example. Arrow functions where **not** built for that case, you probably misunderstand why these were implemented. Either use `function`, either use other approaches. – briosheje Dec 13 '18 at 13:05
  • 1
    Arrow functions are not meant to replace functions, they are for different use cases. – str Dec 13 '18 at 13:06

2 Answers2

3

There is literally no way to access the correct this in an arrow function attached to a constructor prototype.

"use strict";
function Main() {};
Main.prototype.foo = () => console.log(this);
var m = new Main();
m.foo(); // undefined
m.foo.call(m); // still undefined
m.foo.bind(m)(); // you get the idea

Arrow functions' this is closed over in the lexical scope like a normal var, and in this case it's the global (or top-level module) scope. If you remove the "use strict" you'll just get window instead of undefined.

You have a few alternatives:

Don't define on the prototype (don't actually do this):

function Main() {
  this.foo = () => console.log(this);
}

m = new Main();
m.foo(); // correct this!

This works because the arrow function closes over the correct this in the lexical scope of the constructor. But here you lose the advantages of having only one function object shared between instances (since you aren't using the prototype).

Use a normal function

That's already posted in your question, so no need to repeat.

Define a class with method

class Main {
  foo () {
    console.log(this);
  }
}

m = new Main();
m.foo(); // correct this
Jared Smith
  • 14,977
  • 4
  • 36
  • 57
1

Well, as you said, you can't use context with arrow functions. I guess that the next best bet would be to create an enclosed scope to use inside the arrow function:

{ // that
    let db = something;

    Main.prototype.funcX = (dados) => {

        console.log(db + "is only available from inside that block");

    };
}

But still, as pointed out in the comments, you're missing the point of arrow functions.

Lucas Noetzold
  • 1,429
  • 1
  • 10
  • 20