0

In the following snippet I made an event emitter which executes all the event when called. I used a function constructor and added on and emit methods on it.
The even transfer updates the objects property amount.
But when I access this.amount inside on it returns undefined.
emitter.js

function Account(n) {
    this.balance=n;
    this.events = {}
}
Account.prototype.on =  function(type, listener){
    this.events[type] = this.events[type] || [];
    this.events[type].push(listener);
}

Account.prototype.emmit =  function(type){
    if(this.events[type]) {
        this.events[type].forEach(listener => {

            listener();
        });
    }
    console.log("Amount transfered. Total Balance is " + this.balance);
}
module.exports = Account;

app.js

const Account = require('./emitter');

const myAccount = new Account(5);
myAccount.on('transfer', function(amount = 10){
    this.balance += amount;
    console.log(amount + ' Rs. has been transferrered! Balance is ' + this.balance);
});

myAccount.on('transfer', function(amount = 30){
    this.balance += amount;
    console.log(amount + 'Rs. has been transferrered! Balance is ' + this.balance);
});

myAccount.on('transfer', function(amount = 40){
    this.balance += amount;
    console.log(amount + 'Rs. has been transferrered! Balance is ' + this.balance);
});
myAccount.emmit('transfer');

This is what I have already tried.
I think that this.events is already an object so this inside it will refer to the current object not the parent object.
So tried accessing the property myAccount.amount. Still it returns undefined
I also tried storing reference of this in a variable that and instead of accessing property in this.amount, i tried that.amount still undefined.

Sujeet Agrahari
  • 1,887
  • 1
  • 14
  • 32

1 Answers1

2

Your are not passing 'this' to your listener callback function.

Change listener() invocation to this:

listener.call(this);
c-smile
  • 24,546
  • 7
  • 54
  • 79
  • Can you please explain a bit? why this doesn't work `listener(this)` and `listener.call(this) ` works – Sujeet Agrahari Sep 07 '19 at 16:52
  • 1
    this in JavaScript is an *environment variable*, it cannot be passed or set by parameters. In order to call a function and pass `this` into it you shall use either `.call(this,...)`, `.apply(this,...)` or `.bind(this,...)` Check this: https://medium.com/@owenyangg/javascript-call-apply-and-bind-explained-to-a-total-noob-63f146684564 – c-smile Sep 07 '19 at 17:05
  • @SujeetAgrahari You can find a good but general explanation in: "[How does the “this” keyword work?](https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work)" – The value of `this` in a given function depends on how that function was invoked. In this case, calling `listener()` as a plain function will use a global default as the value of `this`, while adding `.call(this)` allows you to provide a value of your choosing. – Jonathan Lonowski Sep 07 '19 at 17:27