简体   繁体   中英

Setting object values in JavaScript

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

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 .

@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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM