user3011902
user3011902

Reputation:

Variable becomes 0 when accessing from within Object

I have created an Object like so:

var Object = function() {
    var value = 0;

    function do() {
        console.log(value);
    }

    return {
        do : do,
        value : value
    }
};
exports.Object = Object;

I am calling the do function from outside of this Object:

function call(object) {
    console.log(object.value);
    object.update();
}

I have set the value to equal 2.5 outside of the player class. The bizarre thing is that when I execute the code, the console logs this:

2.5
0
2.5
0

So it seems that the value is 0 from within the class, but 2.5 when I access it from outside it. What is the issue here?

My background is mainly Java, and I am rather new to Javascript, so perhaps I have missed something trivial.

Upvotes: 2

Views: 346

Answers (3)

Twiknight
Twiknight

Reputation: 39

In fact , your code is equivalent to

var Object = function() {
  var value = 0;

  function do() {
    console.log(value);
  }

  var res= {
    do : do,
    value : value
  }
  return res;
 };
exports.Object = Object; 

the function do() will not log the res.value. Instead it logs a local variable of function Object, that means you can't change the value do returns.

if you want to log res.value, can try following:

function do(){
    console.log(this.value);
}

However I have to mention something else. if value is an object instead of literal. you can easily access it. A closure is unable to protect an object from been changed as object is passed by ref.

Just try this:

var Object = function() {
    var value = [0];

    function doSth() {
        console.log(value[0]);
    }

    var res= {
        do : doSth,
        value : value
    }
    return res;
};
exports.Object = Object; 

Upvotes: 0

Josh
Josh

Reputation: 11070

You have created a closure: You're returning an object which has a property value, but the var value inside the closure does not change when you change the value property of the returned object.

Explained another way, when you say new Object, then you get two values one is returned as a property of the object, and the other is the var object hidden inside the closure.

Try the following:

var Object = function() {
    this.value = 0;

    function do() {
        console.log(this.value);
    }

    return {
        do : do
    }
};

exports.Object = new Object;

Alternatively:

var Object = function() {
    var value = 0;

    function do() {
        console.log(value);
    }

    return {
        do : do,
        getValue : function(){ return value; },
        setValue : function(val){ value = val; }
    }
};

exports.Object = Object;

Upvotes: 2

Jack
Jack

Reputation: 9388

As Josh mentioned, this is a value vs reference issue, which is usually addressed by either returning an object (so it's by reference) or including functions like getValue and setValue.

For the second option, you could actually re-write your function and use getters, like so:

var Object = function() {
    var value = 0;

    function _do() {
        console.log(value);
    }
    function update(val) {
        value = val * .5;
    }
    return {
        do: _do,
        update: update,

        // Our fancy getter!
        get value() {
            return value;
        }
    }
};
exports.Object = Object;

At this point, Object.value would behave similar to getValue.

Since it's Friday, let's go crazy and add our setter as well:

var Object = function() {
    var value = 0;

    function _do() {
        console.log(value);
    }
    return {
        do: _do,

        // Our fancy getters/setters!
        get value() {
            return value;
        },
        set value(val) {
            value = val * .5;
        }
    }
};
exports.Object = Object;

Then you're doing things like:

Object.value; // Returns 0
Object.value = 5;
Object.value; // Returns 2.5
Object.do(); // Logs 2.5

Defining Getters and Setters

Getter/Setter compatibility

Upvotes: 1

Related Questions