[removed] Calling object methods within that objec

2020-02-17 03:22发布

问题:

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.

回答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.



回答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');