2
var MyObj = function(x) {
   this.x = x;
   this.y = 5;
};

MyObj.prototype.example = function() {
   // I want to return a new object which has access to this.x and this.y

   // For example:
   return {
      addTwo: function() {
         // How can I access this.x from the MyObj instance?
         return 2 + (x from the instance of MyObj)
      }
   }
};

How can I return an object from the example method so that it has access to the instance variables from an instance of MyObj?

I can't use 'this' inside the returning object, or else it will refer to the object that I am returning.

And I am not using es6

user7255069
  • 111
  • 1
  • 6

3 Answers3

2

The are a few options - the simplest would be to create a reference to this of your MyObj instance and refer to that in the addTwo() function of the object that example() returns like so:

var MyObj = function(x) {
   this.x = x;
   this.y = 5;
};

MyObj.prototype.example = function() {
   
   // Create local variable to this, called self
   let self = this;
   
   return {
      addTwo: function() {
      
         // Access self field, which is reference 
         // to instance of enclosing object
         return 2 + (self.x);
      }
   }
};

var obj = new MyObj(5);

console.log('should return 5 + 2:', obj.example().addTwo() );

obj.x = 10;

console.log('should return 10 + 2:', obj.example().addTwo() );
Dacre Denny
  • 29,664
  • 5
  • 45
  • 65
2

You didn't state if you can use es6 or not. Basically it's a problem of scope. With es6 and babel you can do something like

ES6 Method

var MyObj = function(x) {
   this.x = x;
   this.y = 5;
};

MyObj.prototype.example = function() {
   // I want to return a new object which has access to this.x and this.y

   // For example:
   return {
      addTwo: () => {
         // How can I access this.x from the MyObj instance?
         return 2 + this.x
      }
   }
};

In this way this won't change as arrow functions are having this context inherited from outer scope.

For the reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Which is basically transpiled to something like this (You are not using classes so I assume you are not using es6)

Old way method

var MyObj = function(x) {
   this.x = x;
   this.y = 5;
};

MyObj.prototype.example = function() {
   // I want to return a new object which has access to this.x and this.y

   var that = this
   // For example:
   return {
      addTwo: function(){
         // How can I access this.x from the MyObj instance?
         return 2 + that.x
      }
   }
};

which will just "store" this variable to other variable for later usage (that's what similarly babel does under the cover).

.bind() method

If you wanna 3rd answer you can bind this context to a called function as this

var MyObj = function(x) {
   this.x = x;
   this.y = 5;
};

MyObj.prototype.example = function() {
   // I want to return a new object which has access to this.x and this.y

   var addTwo = function() {
     return 2 + this.x
   }
   // For example:
   return {
      addTwo: addTwo.bind(this)
   }
};

which will "transfer" this to that function.

For the reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

Milos Mosovsky
  • 2,913
  • 1
  • 16
  • 18
0

If you use arrow functions the this context won't change inside:

var MyObj = function(x) {
   this.x = x;
   this.y = 5;
};

MyObj.prototype.example = function() {
   return {
      addTwo: () => 2 + this.x
   }
};

const o = new MyObj(2);
console.log(o.example().addTwo());
quirimmo
  • 9,800
  • 3
  • 30
  • 45