Reputation:
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
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
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 value
s 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
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
Upvotes: 1