Javascript: Calling object methods within that object

51,399

Solution 1

Well, from your first example:

var _obj = {
    property: value,
    method1: function() {
      // do stuff
    },
    method2: function() {
      // use property
      var prop = this.property; 
      // call method1
      this.method1(); 
    }
  };

That's what the this value is for.

Now, what you cannot do is refer to a property of an "under construction" object from elsewhere in the object literal syntax. (It's hard to give an example because it's just not syntactically possible.) In cases where you want to do that, you do need one or more separate assignment statements.

Solution 2

Guess what? You are making simple stuff complex. Pointy's answer is good, but the prototype way is better for several reasons. That's why I am describing (rather, making corrections in) the last method. Check this fiddle.

var MyObj = function(name) {
  this.name = name;
};

MyObj.prototype = {
  called_often: function() {
    // lots more code than just the following
    return 'VALUE'; //document.getElementById('someID').value;
  },

  global_default: 'value', // can be changed, so need to pull value when run

  does_stuff: function(value) {
    var str = this.global_default + value, // can't access global_default on its own
        input = this.called_often(), // doesn't work; MyObj.prototype.called_often() DOES
        name = this.name; // 'this' used in the prototype doesn't work
                          // even within a created object
    return name + input + str;
  }
};

var obj = new MyObj('Bob');
Share:
51,399
Marcus Hughes
Author by

Marcus Hughes

Updated on March 31, 2020

Comments

  • Marcus Hughes
    Marcus Hughes about 4 years

    What is the best design pattern for achieving the following (which doesn't work)?

    var obj = (function() {
    
      // code defining private variables and methods
    
      var _obj = {
        property: value,
        method1: function() {
          // do stuff
        },
        method2: function() {
          // use property
          var prop = _obj.property; // obviously doesn't work
          // call method1
          obj.method1(); // "obj" not finished being defined yet!
        }
      };
    
      // obviously now I could do...
      var prop = _obj.property;
    
      return _obj;
    
    })();
    
    // and I could now do...
    obj.method1();
    

    A variation which I think should work is

    var obj = (function() {
    
      var property = value,
          method1 = function() {
            // do stuff
          },
          method2 = function() {
            // use property
            var prop = property;
            // call method1
            method1();
          },
          _obj = {
            property: property,
            method1: method1,
            method2: method2
          };
    
      return _obj;
    
    })();
    

    Similarly, how does it work for objects meant to be created with the new operator? Within the constructor function itself you can write this.method(). But what if you want to keep the constructor small, only defining those things which will likely be customized upon creation, and then defining the rest in the prototype? (This seems to be the common pattern.) Can the properties / methods within the prototype interact in any way?

    var MyObj = function(name) {
      this.name = name;
    };
    
    var obj = new MyObj('Bob');
    
    MyObj.prototype = {
      called_often: function() {
        // lots more code than just the following
        return document.getElementById('someID').value;
      },
    
      global_default: 'value', // can be changed, so need to pull value when run
    
      does_stuff: function(value) {
        var str = global_default + value, // can't access global_default on its own
            input = MyObj.called_often(), // doesn't work; MyObj.prototype.called_often() DOES
            name = this.name; // 'this' used in the prototype doesn't work
                              // even within a created object
        return name + input + str;
      }
    };
    

    I'm sure there's better ways to achieve my result whenever I run into this problem. This code isn't situation specific and just illustrates the general problem. So you won't be able to give me an alternative for those specific situations I run into. But maybe you can help my overall thinking.