Search code examples
javascriptconditional-statementsoperator-precedence

Javascript "if" Order of Operations


So let's say you have a really basic person object with two values and one function:

function personObject() {
    this.name = 'First Name';
    this.placeInLine = 1;
    this.setPlaceInLine = function(place) {
        this.placeInLine = place;
    }
}

And we setup some variables like this:

var john = new personObject();
var bill = new personObject();
var message = "";

Now look at the three codes snippets below...

---Code #1---

if(john.placeInLine < bill.placeInLine) message = "John is before Bill";
else message = "John is not before Bill";

RESULT: message = "John is not before Bill"; // because 1 is not less than 1

---Code #2---

bill.setPlaceInLine(2); // change Bill's place to 2 (instead of default of 1)
if(john.placeInLine < bill.placeInLine) message = "John is before Bill";
else message = "John is not before Bill";

RESULT: message = "John is before Bill"; // because 1 less than 2;

---Code #3---

if(john.placeInLine < bill.setPlaceInLine(2)) message = "John is before Bill";
else message = "John is not before Bill";

RESULT: message = "John is not before Bill": // why?

Is the .setPlaceInLine function being called after the comparison? Or is the act of running that function returning something that is then being compared to john.placeInLine?


Solution

  • Because setPlaceInLine method has no explicit return, and therefore returns undefined. And 1 < undefined evaluates to false: undefined gets converted to Number, giving NaN, and 1 < NaN is certainly false (1 > NaN is false too, btw).

    While you can fix this by making your setter method return the assigned value:

    PersonObject.prototype.setPlaceInLine = function(place) {
      return this.placeInLine = place;
    }
    

    ... I think it's better (more clean) to use the setters and getters separately (like in your code #2 example).

    As a sidenote, I'd recommend using prototypes to set up object methods (like I did in my example code). The reason for this is pretty well explained in this answer: basically with prototypes you will make just a single Function entity, used by all the created objects, when with this.someMethod you would create a new Function each time a constructor is called.