3

In Java you could call methods to help you do some heavy lifting in the constructor, but javascript requires the method to be defined first, so I'm wondering if there's another way I could go about this or if I'm forced to call the method that does the heavy lifting after it's been defined. I prefer to keep instance functions contained within the Object/Class, and it feels weird that I would have to have the constructor at the very end of the object/class.

function Polynomials(polyString)
{
    // instance variables
    this.polys = [];
    this.left = undefined;
    this.right = undefined;

    // This does not work because it's not yet declared
    this.parseInit(polyString);

    // this parses out a string and initializes this.left and this.right
    this.parseInit = function(polyString)
    {
        //Lots of heavy lifting here (many lines of code)
    }

    // A lot more instance functions defined down here (even more lines of code)

    // Is my only option to call it here?
}
1
  • 1
    This has to do with hoisting and declarations vs expressions. Commented Jun 22, 2014 at 15:49

3 Answers 3

3

Here's what I would do:

var Polynomials = function() { 
   // let's use a self invoking anonymous function
   // so that we can define var / function without polluting namespace
   // idea is to build the class then return it, while taking advantage
   // of a local scope.

   // constructor definition
   function Polynomials( value1) (
      this.property1 = value1;
      instanceCount++;
      // here you can use publicMethod1 or parseInit
   }

   // define all the public methods of your class on its prototype.
   Polynomials.prototype = {

     publicMethod1 : function() { /* parseInit()... */ },

     getInstanceCount : function() ( return instanceCount; }

   }

  // you can define functions that won't pollute namespace here
  // those are functions private to the class (that can't be accessed by inheriting classes)
  function parseInit() {
  }

  // you can define also vars private to the class
  //  most obvious example is instance count.
  var instanceCount = 0; 

   // return the class-function just built;
   return Polynomials;

}();

Remarks:

Rq 1:

prototype functions are public methods available for each instance of the class.

var newInstance = new MyClass();
newInstance.functionDefinedOnPrototype(sameValue);

Rq2: If you want truly 'private' variable, you have to got this way:

function Constructor() {
   var privateProperty=12;
   this.functionUsingPrivateProperty = function() {  
    // here you can use privateProperrty, it's in scope
   }
}

Constructor.prototype = {
    // here define public methods that uses only public properties
    publicMethod1 : function() {
        // here privateProperty cannot be reached, it is out of scope.
    }
}

personally, I do use only properties (not private vars), and use the '' common convention to notify a property is private. So I can define every public method on the prototype.
After that, anyone using a property prefixed with '
' must take his/her responsibility , it seems fair. :-)

For the difference between function fn() {} and var fn= function() {}, google or S.O. for this question, short answer is that function fn() {} gets the function defined and assigned its value in whole scope, when var get the var defined, but its value is only evaluated when code has run the evaluation.

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

5 Comments

This is like the lost manual I've been looking for, I still have some questions further about the scope and instance vs static functions - time to start playing around and finding some stuff out :) I really like how everything is organized and self contained.
Yes, this is a very clean way of proceeding. I might have other remarks if you're interested.
Are prototyped functions like static methods? That was actually the next question I was going to ask on stackoverflow
Is function parseInit() the same as var parseInit = function() For some reason I feel more at ease with var - as if it's a scope modifier since I'm coming from Java/C# even though I know it's not; this is something I'm going to have to get over.
@CTS_AE It's almost the same. The variable declaration gets hoisted in both cases. However there's an important difference: with a function declaration the whole definition is also hoisted so that you can call the function before it was defined in code, but that's not the case with a function expression.
1

Your 'instance variables' are declared on the 'this' object which if you're looking for a Java equivalent is a bit like making them public. You can declare variables with the var keyword which makes them more like private variables within your constructor function. Then they are subject to 'hoisting' which basically means they are regarded as being declared at the top of your function (or whatever scope they are declared in) even if you write them after the invoking code.

4 Comments

Never knew about hoisting, thanks for the clear straightforward explanation.
I'm not sure if this may work though because I'm trying to reference the instance variables within the parseInit function. I'm assuming I also need to change those over to private/var as well.
Ah, then you might need to do the slightly weird-looking assignment of this to a variable, a la var that = this;. Then when you want to update this.foo in your inner function, you refer to that.foo instead. This is because the this keyword in Java is a bit funky, in that it will apply to the inner function scope rather than your constructor function scope.
I remember I had to do this little hacky get around on a project about 2 years ago; I completely forgot about it until now, thanks.
0

I would create a function declaration and then assign the variable to the function declaration. The reason being that JavaScript will hoist your function declarations.

So you could do this:

function Polynomials(polyString) {
    // instance variables
    this.polys = [];
    this.left = undefined;
    this.right = undefined;

    // this parses out a string and initializes this.left and this.right
    this.parseInit = parseInitFunc;

    // This does not work because it's not yet declared
    this.parseInit(polyString);

    // A lot more instance functions defined down here (even more lines of code)

    function parseInitFunc(polyString) {
        console.log('executed');
    }

    // Is my only option to call it here?
}

That way your code stays clean.

jsFiddle

5 Comments

But it still won't hoist the expression, so this.parseInit = fn; still won't be defined, and you can't do function this.parseInit() {...
Now you've added some code, but it's exactly the same as the OP's, there's no difference ?
@adeneo, it does need some more cleaning up (like changing my comments) but he's hoisting the "function parseInitFunc", and then assigning to to this.parseInit and then calling that, at least that's what I believe should happen, I haven't yet tried this, but I never knew about "hoisting" until now. Rom99's explanation worked better for me and quicker, but that link definitely goes into some deep details :)
@CTS_AE - Uhm, no! The function is called before the expression, so it's exactly the same, this doesn't change anything.
Now it would work, with the order changed, but it's still the same as CTS_AE mentions in the question, just calling the function after it's defined would of course work.

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.