JavaScript confused on setting javascript object property value

I am creating an object

var testobj=function(x)
{
    var b,c;
    var a=x;
    var init=function(d,e,f)
    {
        a=d;
        b=e;
        c=f;
    };
    return{
        init:init,
        b:function(){
        return b;
        },
        a:a,
        c:c   
    }
};
//here some test of the object
var instobj=new testobj(4);
instobj.init(1,2,3);
alert(instobj.a);  //display 4
alert(instobj.b()); //display 2
alert(instobj.c); //display nothing

I don't understand why I can't get value of 'c' by simply reference to it, instead, I need to use a function to return that value.

Answer:1

What happened?

I expected you to use the function object when you used new, but you returned an object.

-->return{
    init:init,
    b:function(){
    return b;
    },
    a:a,
    c:c   
}

Usually new isn't used when an object is being returned. When this happens, the context of the function object is lost, as a result, this is what the returned object's init function looks like

function(d,e,f)
{
    a=d;
    b=e;
    c=f;
};

with literally no reference to anything else. At this point you are in a global scope (unless bind was used which is a different issue) causing a,b, and c to now be defined globally (assuming strict is not being used). So what this accomplishes is to create 3 global variables and then assign them to the values.

As a result, this is what ends up happening in your calls at the very end.

You first start by assigning the three global variables a,b, and c to 1,2, and 3

instobj.init(1,2,3);

Next, you alert the value of a, which was still referenced by your returned object, and took a value from the constructor of 4. As a result 4 is alerted

alert(instobj.a);  //display 4 (because that came from the constructor)

In the following line, you reference a function which has no context and as a result is referencing global scope. The variable it returns is the global variable b, set above with init to 2

alert(instobj.b()); //display 2 (this returned b, a global variable)

The last call is to c. However, c is still referencing the original function object's variable c, and that was only declared once but never assigned to. (remember? var b,c;. If this were var a,c=-1; then the following code would alert -1).

alert(instobj.c); //display nothing (undefined from var b,c;)

What could be changed?

Usually a prototypal approach is taken in javascript. This means you set up a constructor, define some prototype functions that each instance will use, and then new up instances of those. For your testobj, that would look like this:

function Test(x){
 this.a = x;
 this.b = undefined;
 this.c = undefined;
}
Test.prototype.init = function(d,e,f){
 this.a = d;
 this.b = e;
 this.c = f;
};

When new is used, this refers to the instance of the function object. Later, when referencing the variable the instantiation was assigned to, the . property name may be used to reference this. property values.

Also when new is used, functions attached to the prototype are included in the instantiated object. Their scope is the same this as described above, and the property references will be the same as well.

As a result, you may access your test object like this:

var testobj = new Test(4);
testobj.init(1,2,3);
alert(testobj.a);//1
alert(testobj.b);//2
alert(testobj.c);//3

jsFiddle Demo

Link to top of answer

Answer:2

I have a question about Javascript. I want to set some paragraphs on my page to hidden when the page loads, then have the paragraphs accessed by clicking on the heading. This is the html: <div id="...

I have a question about Javascript. I want to set some paragraphs on my page to hidden when the page loads, then have the paragraphs accessed by clicking on the heading. This is the html: <div id="...

Lazy loading tests: I am trying to build a test for Jasmine to test a method that uses Q.delay. To go around the 10 seconds wait i'm using Jasmine's clock: jasmine.Clock.tick(10010); This works on ...

Lazy loading tests: I am trying to build a test for Jasmine to test a method that uses Q.delay. To go around the 10 seconds wait i'm using Jasmine's clock: jasmine.Clock.tick(10010); This works on ...

  1. jasmine clock tick not working
  2. jasmine clock tick example
  3. jasmine clock tick
  4. jasmine.clock().tick(10)
  5. jasmine.clock.tick is not a function
  6. jasmine clock tick promise
  7. jasmine.clock().tick(101)

I'm having a problem with a jQuery function that appends tags, but it only occurs about 40% of the time. My tags are not completely wrapping my text. Here is my code: $.getJSON('/ycomb', function(...

I'm having a problem with a jQuery function that appends tags, but it only occurs about 40% of the time. My tags are not completely wrapping my text. Here is my code: $.getJSON('/ycomb', function(...

I am working with JSP and I have a HTML form in which I have a button at the top which is Process button. Now if I click on that Process button, it shows me a form which has two radio button - ...

I am working with JSP and I have a HTML form in which I have a button at the top which is Process button. Now if I click on that Process button, it shows me a form which has two radio button - ...

  1. make textbox mandatory html
  2. make textbox mandatory asp.net
  3. make textbox mandatory c#
  4. wpf make textbox mandatory
  5. vba make textbox mandatory
  6. jquery to make textbox mandatory
  7. how to make textbox mandatory using javascript
  8. how to make textbox mandatory in vb.net
  9. how to make textbox mandatory
  10. how to make textbox mandatory in mvc