0

Is there a way to create an object in Javascript such that all of its methods are available to the constructor?

I'm finding it tough to phrase my problem clearly.. so an example!

Given this class

function Example() {
  var someVar = something;
  var moreState = initializedToSomethingElse; 

  verifySomething(); <-- Fails! 

  this.verifySomething = function() {
    // do verify stuff
  }
}

I can't call verifySomething in my constructor because the method, as far as the instance is concerned, doesn't exist yet. So, I get an undefined error. Is there a better way to create objects in javascript so that I can avoid this problem?

3
  • 2
    Why not just call it after defining it? jsfiddle.net/th6kmsa4 Commented Nov 21, 2014 at 14:04
  • Honestly, may be kinda dumb, but for aesthetic reasons. I like having all the initialization code blocked together in one spot rather than spread throughout function declarations. Commented Nov 21, 2014 at 14:06
  • Asthetically I might prefer to use colon's instead of periods (this::verifySomething()). The language just doesn't work that way! Commented Nov 21, 2014 at 14:10

1 Answer 1

5

Is there a way to create an object in Javascript such that all of its methods are available to the constructor?

You can call any method once it's been created. In your example, there are two issues:

  1. You haven't created the method yet

  2. You are calling it incorrectly — in JavaScript, using the object qualifier (this. within a constructor, usually) isn't optional as it is in some other languages

If you define methods on the constructor function's prototype property, provided those assignments happen before the call to the constructor (which is usually true, and there are techniques for guaranteeing it), the methods will be available on this within the constructor. If you create methods within the constructor (as in your example), just create them first.

Here's your example using the constructor's prototype property, which refers to the object that will be used as the prototype of instances created via new:

function Example() {
  var someVar = something;
  var moreState = initializedToSomethingElse; 

  this.verifySomething(); // <== Works
}
Example.prototype.verifySomething = function() {
    // do verify stuff
};

var e = new Example();

Here's an example defining within the constructor that makes use of the fact that function declarations (rather than expressions) are "hoisted" (completed before any step-by-step code runs).

function Example() {
  var someVar = something;
  var moreState = initializedToSomethingElse; 
  this.verifySomething = verifySomething; // <== Note we assign first

  this.verifySomething(); // <== Works

  function verifySomething() {
      // do verify stuff
  }
}

var e = new Example();

If you really don't like doing that assignment before calling it, you could use .call:

function Example() {
  var someVar = something;
  var moreState = initializedToSomethingElse; 

  verifySomething.call(this); // <== Works
  // this.verifySomething();  // <== Would not work

  this.verifySomething = verifySomething; // <== Note we assign after
  function verifySomething() {
      // do verify stuff
  }
}

var e = new Example();

I mentioned above that there are techniques for guaranteeing that the prototype property of the constructor function has been fully fleshed-out before the constructor is ever called. Here's one of them (using a scoping function):

var Example = (function() {
    function Example() {
      var someVar = something;
      var moreState = initializedToSomethingElse; 

      this.verifySomething(); // <== Works
    }
    Example.prototype.verifySomething = function() {
        // do verify stuff
    };

    return Example;
})();

var e = new Example();

With the above, there's no way code outside the containing immediately-invoked scoping function can use Example until after that scoping function has finished, and therefore fully set up the prototype property.

Sign up to request clarification or add additional context in comments.

2 Comments

Fantastic answer! Thanks for all the examples!
@user3308774: No problem, glad that helped. If you like to use class-like mechanisms with JavaScript's prototypical inheritance, or just want to cut down on verbosity, you may find my little helper script handy: Lineage

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.