Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can someone explain odd JavaScript with objects?

Tags:

javascript

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?

like image 639
Johan Sundström Avatar asked Aug 27 '15 12:08

Johan Sundström


Video Answer


4 Answers

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.)

like image 54
Pointy Avatar answered Oct 18 '22 00:10

Pointy


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
like image 24
Adam Avatar answered Oct 17 '22 22:10

Adam


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..

  • Implementing private instance variables in Javascript
like image 3
3 revs Avatar answered Oct 17 '22 23:10

3 revs


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
like image 1
starikovs Avatar answered Oct 17 '22 23:10

starikovs