0

When I'm trying to create a new constructor object within another constructor function, I can't use this.time when I create the object. But I can use this.time in a method and return the value. How come it is like this?!

I only get undefined in return when I run the second console.log. It's about this line: timeControl: new TimeControl(this.time) If I use a value like 33 it works fine, but not with this.time Interested and curious why the code act like this?

(To minimize the code in this question, I'm not showing the TimeControl constructor)

    // Box
Box = function(x,y,value) {
    this.x = x;
    this.y = y;
    this.time = value;
    // Create a new object of TimeControl
    //this.timeControl = new TimeControl(this.time); // OK to create object here!
}
Box.prototype = {
    // Create a new object of TimeControl
    timeControl: new TimeControl(this.time), // But not OK here! Works if I enter a number
    test1: function() {
        return this.time;
    },
    test2: function() {
        return this.timeControl.getTime();
    }
};

var box = new Box(10,10,14);
console.log("Duration: " + box.test1()); // Works fine
console.log("Duration: " + box.test2()); // Returns undefined if this.time is used
3D-kreativ
  • 8,373
  • 34
  • 86
  • 150
  • `this` has meaning inside of a function. There's no function there. – elclanrs Aug 26 '14 at 05:07
  • In the second case, `this` is not bound to any value. What value would you expect it to have? (If you expect to have a different `time` value for each instance of `Box`, then `timeControl` doesn't belong in the prototype.) – Ted Hopp Aug 26 '14 at 05:07
  • @TedHopp But don't 'this.time' get the value from the 'value' variable in the Box constructor? – 3D-kreativ Aug 26 '14 at 05:09
  • I'd say this is a duplicate of the famous http://stackoverflow.com/questions/3127429/javascript-this-keyword. Asking about `this` requires an understanding of `this`. – elclanrs Aug 26 '14 at 05:10
  • No, because JavaScript needs to evaluate `this.time` when it is building the object to assign to the prototype. – Ted Hopp Aug 26 '14 at 05:10
  • Hmm, it's a little bit complicated to understand! ;) But why can I get the value with the call to the 'test1' method? Could it be done in another way? I have to leave and I will continue later with this question. Thanks! – 3D-kreativ Aug 26 '14 at 05:20
  • Maybe the following answer can help you understand how you can and can't use prototype: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Aug 26 '14 at 09:39

3 Answers3

0

change timeControl to a function then return new TimeControl from it because inside prototype this is holding the ref of window object .

TimeControl = function(time){
this.time=time;
    console.log('time control initialized time is ='+this.time);
}
TimeControl.prototype = {
    getTime:function(){
    return this.time;
    }
}
Box = function(x,y,value) {
    this.x = x;
    this.y = y;
    this.time = value;
    // Create a new object of TimeControl
    //this.timeControl = new TimeControl(this.time); // OK to create object here!
}
Box.prototype = {
    xyz:this.time,//here this.time is undefined as this is holding ref of window object
     // Create a new object of TimeControl
    timeControl:function(){return  new TimeControl(this.time)}, // But not OK here! Works if I enter a number
    test1: function() {
        return this.time;
    },
    test2: function() {
        return this.timeControl().getTime();
    }
};

var box = new Box(10,10,14);
console.log("Duration: " + box.test1()); // Works fine
console.log("Duration: " + box.test2()); // Returns undefined
console.log("xyz: " + box.xyz); 

http://jsfiddle.net/vikrant47/df6bgk8L/2/

vikrant singh
  • 2,013
  • 1
  • 10
  • 15
0

When you define function in object property like timeControl: new TimeControl(this.time), this function immediately invokes. So this will be window. Solution for this - use anonymous function:

BoxPrototype: {
    timeControl: function() {
        return new TimeControl(this.time);
    }
}

Or init TimeControl in constructor function:

Box = function(x, y, value) {
    this.time = new TimeControl(value);
}

Box.prototype = {
    getTimeControl: function() {
        return this.time;
    }
}
Eugene Obrezkov
  • 2,626
  • 2
  • 14
  • 32
0

To understand why "this" is not working, you have to understand how this and scopes work in javascript. in javascript you have only two scopes, Global scope and Function scope.

When you create a object using new operator, you are essentially setting the context of the new object to this.so this will point at the new object.And also since functions have its own scope the first code works.

When you use the object literal(second snippet) for creating a object. the keyword this would point at the global object(depending on the context).since you don't have a property called time in the global object, this.time does not work.Object literals are javascript expression and they dont create a scope by themselves.the scope is decided based on where they are living.

i would modify the prototype object on these lines

Box.prototype = ({
  timeControl: null,
  test1: function() {
    return this.time;
  },
  test2: function() {
    return this.timeControl.getTime();
  },
  setTimeCtrl: function() {
    //set the timecontrol object here
    this.timeControl = new TimeControl(this.time);
    return this;// return the newly created object
  }
}).setTimeCtrl(); //invoke it as soon as you create the object

this makes sure the object is created and then necessary properties are set afterwards

Prabhu Murthy
  • 8,614
  • 5
  • 26
  • 34