1

Will this calc function be defined once (put on the prototype chain for the 'obj' variable)? If not, then how can I get the calc function on the prototype chain so all instantiations of Obj will reference the same calc function?

I tried assigning the calc function to Obj.prototype.calc, but then when 'obj' is created, it can't find it in the creation process.

window.onload = function () {
    var Obj = function (obj) {
        var calc = function (o) {
            for (p in o) {
                if (o.hasOwnProperty(p) && typeof o[p] === 'function') {
                    o[p] = o[p]();
                }
            }
            return o;
        };
        return calc(obj);
    };

    function test() {
        var obj = new Obj({
            a: 1,
            b: 2,
            c: function () {
                return this.a + this.b;
            },
            d: function () {
                return this.b * this.c;


   }
    });
    window.console.log(obj.a); // 1
    window.console.log(obj.b); // 2
    window.console.log(obj.c); // 3
    window.console.log(obj.d); // 6
}
test();

}

The purpose of the Obj constructor is creating an object literal type syntax when I define many versions of 'obj' but allowing the use of the 'this' keyword to calculate properties in terms of other properties in each object.

Here is the version with the prototype definition which doesn't work:

<!DOCTYPE HTML>
<html>
<head>
<script>
window.onload = function () {
    var Obj =   function (obj) {
                    return calc(obj);
                };
    Obj.prototype.calc = function (o) {
                            for (p in o) {
                                if (o.hasOwnProperty(p) && typeof o[p] === 'function') {                        
                                    o[p] = o[p]();
                                }
                            }
                            return o;
                        };
    function test() {
        var obj = new Obj({
            a:      1,
            b:      2,
            c:      function () {return this.a + this.b;},
            d:      function () {return this.b * this.c;}
        });
       window.console.log(obj.a); 
       window.console.log(obj.b); 
       window.console.log(obj.c); 
       window.console.log(obj.d); 
    }
    test();   

}
</script>
</head>
<body>
</body>
</html>
ciso
  • 2,887
  • 6
  • 33
  • 58
  • 3
    Because you left out `var` in the definition of your "calc" function, it's **global**. – Pointy Mar 05 '14 at 18:08
  • Thanks. I added var to prevent it from going global. – ciso Mar 05 '14 at 18:21
  • Btw, you could (should) shorten that to `var Obj = calc = function(){…}`. That `calc` is assigned to a global variable is a bad prctise, but not an actual issue since it's not a closure. – Bergi Mar 05 '14 at 18:22
  • Instead of that `hasOwnProperty()` attempt, you should [define your `Object.prototype` method properly](http://stackoverflow.com/q/13296340/1048572) – Bergi Mar 05 '14 at 18:23
  • @Bergi Do you mean: if (Obj.prototype.calc.hasOwnProperty(p)) {...}? I'm using o.hasOwnProperty to make sure I only process properties (a - d) on the object I'm defining. I read your link but am confused by your comment. – ciso Mar 05 '14 at 18:39
  • No, I meant that you could omit the `o.hasOwnProperty(p) && ` in the if condition. There shouldn't be any enumerable properties that are inherited. – Bergi Mar 05 '14 at 18:42

1 Answers1

2

Will this calc function be defined once (put on the prototype chain for the 'obj' variable)?

No, it gets re-created every time your Obj function is called. (Also note that as Pointy, er, pointed out, you're falling prey to The Horror of Implicit Globals with your calc symbol.)

If not, then how can I get the calc function on the prototype chain so all instantiations of Obj will reference the same calc function?

By putting it there, and then using it from there:

Obj.prototype.calc = /* ...the function, use `this` rather than an argument... */;

and in Obj:

this.calc(); // No `return` needed

Simplified example:

var Foo = function(x, y) {
    this.x = x;
    this.y = y;
    this.calc();
};
Foo.prototype.calc = function() {
    this.z = this.x + this.y;
};

var f = new Foo(2, 3);
console.log(f.z); // "5"
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thank you. I left off the "this" when calling calc. It works now. Still getting the hang of 'this' and prototypes. – ciso Mar 05 '14 at 18:13