6

I have the following class

function Temp() { 
  var isHot=false; 
  return { 
    setHot: function(v) { isHot=v }, 
    getHot: function() { return isHot; },
    hot: isHot
  }
}
var w = new Temp();
w.setHot(true);

w.hot !== w.getHot()

Why do I only see the changed value if I access the w object through a function?

4 Answers4

9

The property "hot" of your returned object is initialized when the object is created, but it's value is a copy of the value of "isHot". Subsequent changes to the local (closure) variable "isHot" will not affect the "hot" property; that's simply not how variables and object properties work.

JavaScript doesn't provide a way to make a variable or object property be an alias for another. What you can do, however, is return a somewhat fancier object:

function Temp() { 
  var isHot=false; 
  return { 
    setHot: function(v) { isHot=v }, 
    getHot: function() { return isHot; },
    get hot() { return isHot; }
  }
}

That creates the "hot" property as an ES6 getter function. A reference to the "hot" property now causes that little function to be invoked, so the property will provide a way to retrieve a copy of the current value of "isHot". (This won't work in older JavaScript environments.)

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Your answers are usually explanatory enough, still they don't make the image of your account less disgusting -- Dracula looks beautiful in contrast to it. – Vidul Aug 27 '15 at 12:57
  • 1
    @Vidul ha ha - well [the painting from which that's taken](https://www.oneonta.edu/faculty/farberas/arth/Images/ARTH_214images/van_eyck/arnolfini/painting.jpg) is very beautiful, though the subject is quite strange. It's in the National Gallery in London and I highly recommend a visit :) – Pointy Aug 27 '15 at 12:58
  • Thank you for the recommendation :) I will probably. My criteria is the [Expressionism](http://www.vangoghmuseum.nl/en) though. – Vidul Aug 27 '15 at 13:01
4

Because hot is set to be the value of isHot at the time that Temp is executed. Because isHot is a primitive, the value of w.hot is a copy of isHot and not a reference to the current value is isHot

It's also worth pointing out that this is a terrible pattern to use if you plan on creating multiple instances of Temp because isHot is a local variable to Temp and not an instance variable of the objects created from new Temp()

var x1 = new Temp();
var x2 = new Temp();
x2.setHot(false);
x1.setHot(true);
x1.getHot() === true; //will return true
Adam Jenkins
  • 51,445
  • 11
  • 72
  • 100
3
function Temp() { 
  return { 
    setHot: function(v) { this.hot=v }, 
    getHot: function() { return this.hot; },
    hot: false
  }
}
var w = new Temp();
w.setHot(true);

w.hot !== w.getHot()

This, i believe, is what you would need to do for it to work. No need at all for the isHot var at all. The get set methods then directly edit the objects hot value, which means both getHot() and w.hot will return the right value.

If you wanted to make the isHot value private, then i believe you would need to use the isHot var, but you would not need or reference the w.hot value at all. Not sure what the consequences of such an action would be.

function Temp() { 
var isHot = false;
  return { 
    setHot: function(v) { isHot=v }, 
    getHot: function() { return isHot; }
  }
}
var w = new Temp();
w.setHot(true);
w.getHot();

However you can not access w.isHot, essentially private var.

Related articles perhaps..

Community
  • 1
  • 1
Emile
  • 11,451
  • 5
  • 50
  • 63
  • And if you create another instance of `Temp`, you'll confuse yourself for days by wondering why when you `setHot(true)` on one instance it sets `getHot()` to `true` on all your instances. There's no such thing as private instance variables in JavaScript without some really nasty hackery (like the `WeakMap` example in the link you provided). – Adam Jenkins Aug 27 '15 at 13:26
  • ha ha, yeah, that is a very good point! Feel free to edit the post to make that point more pertinent. – Emile Aug 27 '15 at 13:30
1

The above answers explain that you deal with a copy of the source variable. It would be a good tone if you use just get/set functions to get or set the variable value in the closure, preserving the isHot as a private variable:

function Temp() { 
  var isHot=false; 
  return { 
    setHot: function(v) { isHot=v }, 
    getHot: function() { return isHot; }
  }
}
var w = new Temp();
w.setHot(true);

w.getHot(); // always returns the right value
starikovs
  • 3,240
  • 4
  • 28
  • 33