0

I'm trying to build an object in javascript using self-invoking functions to set the object properties – something similar to this:

function Test() {
    this.number = 10;
    this.square = (function(test) {return test.number * test.number}(this));
}

But when I do this:

var test = new Test();

console.log(test.number + " * " + test.number + " = " + test.square);
test.number = 20;
console.log(test.number + " * " + test.number + " = " + test.square);

The console output is:

10 * 10 = 100
20 * 20 = 100

Why is this? Is there any way to call the self-invoking function more than once? I am trying to use this in order to avoid scoping problems

treppo
  • 547
  • 4
  • 17

5 Answers5

1

The whole point of the self-invoking function is that it gets called right when it's declared. If you don't want that, you should make it a normal function, and call it with test.square().

JW.
  • 50,691
  • 36
  • 115
  • 143
1

You're creating an anonymous function that calcuates the quare of the .number member of its argument, and calling it with this. The calculation is done, once and for all, and the result (100 since this.number is 10 at this point) is stored in self.square.

To reflect changes in the .number attribute, you'll have to make it a regular method to be called to calculate the square on demand. Javascript doesn't have properties (not in a cross-browser way, that is) to hide the method call and make it look like a regular attribute access (and even then, the syntax for declaring one would be different).

  • So it is called only once upon creation. I use it to calculate a lot of complex measures in a model of a real-world object, that is why I wanted to avoid normal functions because scoping is getting quite complex. – treppo Jul 26 '11 at 15:39
0

I think

this.square = (function(test) {return test.number * test.number}(this));

actually stored the result of the call of the function? "(this)" at the end of the statement makes me think you called the function, rather than storing the function at this.square as I think you wanted to ...

DWoldrich
  • 3,817
  • 1
  • 21
  • 19
0

Like everyone else is saying, test.square is calculated once when you instantiate the object, and never again. From what you're saying, I believe you want to create properties and not functions, so I would create your object to take in parameters.

function Test(numberArgument) {
this.number = numberArgument;
this.square = ....etc
}
0

The function you use actually returns a static number based on the this.number at the time of creation of the object. You probably want to return a function that return the square of this.number every time it is called:

this.square = (function(test) {return function(){return test.number * test.number;}})(this);
//(this) goes outside the parentheses

You can call it by:

var test = new Test();
test.square();  //returns 100
test.number = 50;
test.square();  //returns 2500
Digital Plane
  • 37,354
  • 7
  • 57
  • 59
  • According to JSLint "(this)" goes inside: http://stackoverflow.com/questions/4979252/jslint-error-move-the-invocation-into-the-parens-that-contain-the-function – treppo Jul 26 '11 at 15:35
  • True, but there are [examples](http://stackoverflow.com/questions/3921922/what-does-this-mean-function-x-y-a-b-in-javascript) of the other syntax. I think `(function(){})()` is more clear, but both may work. – Digital Plane Jul 26 '11 at 15:42