Reza Arani
Reza Arani

Reputation: 66

Array of functions in Javascript object

I need to create an object within array of functions which should be called inside of object. but myObj.myFunctions is always undefined inside of my object after creation.

here is my example code

var myObj = {
      myValue:"My Callback function has been Called",
      myFunctions: [this.myCallback,this.myCallback2],
      init: function(){
        //I need to call this.myFunctions[0...etc]  as callback
        //this.myFunctions[0]() //<-- Here is the error
        console.log(this.myFunctions); //<-- always undefined
      },
      myCallback:function(){
         console.log(this.myValue);
      },
      myCallback2:function(){
         console.log(this.myValue+" Second Callback");
      }
}
var createObject = Object.create(myObj);
createObject.init();
 
 

any idea how could I create array of functions as property of main object? Thanks

Upvotes: 1

Views: 4199

Answers (2)

KShewengger
KShewengger

Reputation: 8269

You need to Create a function inside your myFunctions and return those array of callbacks:

Method #1

var myObj = {
  myValue:"My Callback function has been Called",
  myFunctions: function () {                       // Assign a function and return those array of callbacks
    return [this.myCallback,this.myCallback2];
  },
  init: function(){
    return this.myFunctions();
  },
  myCallback:function(){
    console.log(this.myValue);
  },
  myCallback2:function(){
    console.log(this.myValue+" Second Callback");
  }
};

var createObject = Object.create(myObj);
var functions    = createObject.init();

console.log(functions);    // [f(), f()] 
                           // f for short-term of 'function'

Method #2 - Using direct () function call is already supported for cleaner code

var myObj = {
  myValue:"My Callback function has been Called",
  myFunctions() { 
    return [this.myCallback, this.myCallback2] 
  },
  init() { 
    return this.myFunctions(); 
  },
  myCallback(){
    console.log(this.myValue);
  },
  myCallback2(){
    console.log(this.myValue+" Second Callback");
  }
};

Method #3 - Using ES6 Spread Operator and Replace 'this' to 'myObj'

const myObj = {
  myValue:"My Callback function has been Called",
  myFunctions: () => [myObj.myCallback, myObj.myCallback2],
  init: () => myObj.myFunctions(),
  myCallback: () => console.log(myObj.myValue),
  myCallback2: () => console.log(`${myObj.myValue} Second Callback`)
};

Upvotes: 2

Akrion
Akrion

Reputation: 18515

The concept which you are fighting against is the meaning of this when you call/host your callback functions inside of the array. When done that way this becomes the array and thus you do not get the expected result. One way to get that result could be using call and transform your object so it can be instantiated like this:

var myObj = function() {
  this.myValue = "My Callback function has been Called",
  this.init = function() {
    this.myFunctions[0].call(this)  // <-- pass the proper `this`
    this.myFunctions[1].call(this)
  },
  this.myCallback = function() {
    console.log(this.myValue);
  },
  this.myCallback2 = function() {
    console.log(this.myValue + " Second Callback");
  },
  this.myFunctions = [this.myCallback, this.myCallback2]
}
var createObject = new myObj()
createObject.init();

Another way would be via bind but that is hardly recommended these days so I would skip it and head towards a recommendation which I think you should consider:

class MyObj {
  constructor(val) {
    this.myValue = val;
  }
  myCallback() {
    console.log(this.myValue + " - First Callback");
  }
  myCallback2() {
    console.log(this.myValue + " - Second Callback");
  }
  get myCallbacks() {
    return ['myCallback', 'myCallback2']
  }
  init() {
    this[this.myCallbacks[0]]()  // <-- no issues with `this` anymore
    this[this.myCallbacks[1]]()
  }
}
var createObject = new MyObj('foo')
createObject.init();

Host your callback as string keys in your myCallbacks array in your class. That way you can call them via property accessor and not worry about the this context since at this time it would be the one you expect - the class.

Upvotes: 1

Related Questions