Reputation: 1641
I've tried my best to work this out, now I'm stuck, why does the fourth alert return undefined?
function buttonClick()
{
var myTest = function()
{
var _setDirectlyInside = "So far so good...";
var _setInFunctionCalledInside;
var _setInFunctionCalledFromOutside;
(function(){
_setInFunctionCalledInside = "This would indicate scope isn't the problem?";
})();
return {
basic : "Easy stuff",
setDirectlyInside : _setDirectlyInside,
setInFunctionCalledInside : _setInFunctionCalledInside,
functionCallFromOutside : function(){
_setInFunctionCalledFromOutside = "Why does this come back as undefined?";
},
setInFunctionCalledFromOutside : _setInFunctionCalledFromOutside
}
};
var test = myTest();
alert(test.basic); // Returns "Easy stuff"
alert(test.setDirectlyInside); // Returns "So far so good..."
alert(test.setInFunctionCalledInside); // Returns "This would indicate scope isn't the problem?"
test.functionCallFromOutside();
alert(test.setInFunctionCalledFromOutside); // Broken, returns undefined
}
Resolution:
setInFunctionCalledFromOutside : _setInFunctionCalledFromOutside, // Won't work
setInFunctionCalledFromOutsideGetter : function(){
return _setInFunctionCalledFromOutside; // Will work
}
...
alert(test.setInFunctionCalledFromOutside); // Broken, returns undefined
alert(test.setInFunctionCalledFromOutsideGetter()); // Now works
Upvotes: 1
Views: 94
Reputation: 26696
To add to the others - for reference, JS passes strings and numbers by value. It passes/assigns objects, arrays and functions by reference.
This isn't quite the snag that you're hitting (because your internal variable is undefined
by the time you assign it to your external variable), but even if you did get the first part fixed:
var internal = "string";
return {
external : internal,
setInternal : function (val) { internal = val; }
};
That still doesn't fix the problem, as obj.external
will always continue to be "string".
Why?
Because you set external
to be the same value as internal
at the time of assignment, and not to be equal to a reference
of internal
(ie: a pointer to it).
If you're looking for a pointer, then make internal
an object:
var internal = { string : "my string" };
return {
external : internal,
setInternal : function (val) { internal.string = val; }
};
obj.external.string; // "my string"
obj.setInternal("Bob was here");
obj.external.string; // "bob was here"
Why does it now work?
Because internal is an object, and when you assign external
's value, you give it a pointer to the object which internal
also has a pointer to.
When you change a property of internal
, like internal.string
, because external
points to the same object, external.string
has the same value.
If you set internal
to something completely different, then you're pointing internal
at something else (like internal = null;
), therefore external
will no longer change, when you modify internal
, because internal
is no longer pointing at the object which it used to be.
Upvotes: 1
Reputation: 91497
@nnnnnn said it best, but he deleted his answer. setInFunctionCalledFromOutside
is not a pointer to _setInFunctionCalledFromOutside
. At the time the returned object was created, setInFunctionCalledFromOutside
was assigned the value that _setInFunctionCalledFromOutside
had. Since, no value had yet been assigned, the value was undefined
. Changing the value of the one, doesn't change the value of the other.
A simpler example that illustrates the same principle:
var i = 0;
var n = i;
i++;
alert(i); // 1
alert(n); // still 0
Upvotes: 1
Reputation: 78840
This:
return {
basic : "Easy stuff",
setDirectlyInside : _setDirectlyInside,
setInFunctionCalledInside : _setInFunctionCalledInside,
functionCallFromOutside : function(){
_setInFunctionCalledFromOutside = "Why does this come back as undefined?";
},
setInFunctionCalledFromOutside : _setInFunctionCalledFromOutside
}
...will not cause setInFunctionCalledFromOutside
to always return the same value of _setInFunctionCalledFromOutside
. Rather, _setInFunctionCalledFromOutside
will be evaluated at the time the return
statement executes, and its value will be placed in setInFunctionCalledFromOutside
. Thus, functionCallFromOutside()
will have no effect on setInFunctionCalledFromOutside
.
Upvotes: 2