Search code examples
javascriptpropertiesundefinedecmascript-5

Why is an IF statement affecting whether an object is defined?


I am modifying some JavaScript for a game mod which returns information for use by HTML.

Originally this code looked as follows:

  model.foreign_intelligence = ko.computed(function () {
    var primary = model.selection.system().star.ai()
    var commanders = []
    if (primary) {
      commanders.push(intelligence(primary))
      if (primary.minions) {
        commanders = commanders.concat(primary.minions.map(intelligence))
      }
      if (primary.foes) {
        commanders = commanders.concat(primary.foes.map(intelligence))
      }
    }
    return commanders
  })

For HTML layout reasons I wanted to move primary.foes into a separate block. After some fiddling I ended up with the following:

  model.ffa_opponents = ko.computed(function () {
    var primary = model.selection.system().star.ai()
    var commanders = []
    if (primary) {
      if (primary.foes) {
        commanders = primary.foes.map(intelligence)
      }
    }
    return commanders
  })

I am stumped by something though, which is that if I remove the if (primary) check around if (primary.foes), then primary.foes is coming back as undefined I get an "Cannot read property 'foes' of undefined" exception. I don't understand why an IF check is able to affect the existence of an object.

Unfortunately my knowledge of JavaScript is very limited and I've been mainly beating problems through brute force. I was hoping someone might explain, and then perhaps suggest how this code should better be structured. It strikes me that this IF nesting is unnecessary, but it's the only way I've made it work so far.


Solution

  • Although you write "...then primary.foes is coming back as undefined", you confirmed in comments that the actual error message is:

    Cannot read property 'foes' of undefined

    ...which means that primary itself is undefined.

    In JavaScript undefined is a "falsy" value, so when you do if (primary) and primary is undefined, it will not execute the if block. So it does make sense to have that if.