Home > Mobile >  Ternary not working correctly in array .find method JavaScript
Ternary not working correctly in array .find method JavaScript

Time:07-14

I encountered some perplexing behavior in using a ternary within the .find method of an array. When searching for an object:

Consider this:

const list = [
  { id: 1, name: "dave"},
  { id: 3, name: "choi"},
  {id: 4, name: "bob"}
]

// this works
let isBoy = true
console.log(list.find(v => v.name === isBoy ? "dave" : "choi"))


// this don't work
isBoy = false
console.log(list.find(v => v.name === isBoy ? "dave" : "choi"))

// this always works: use () around ternary
console.log(list.find(v => v.name === (isBoy ? "dave" : "choi")))
isBoy = true
console.log(list.find(v => v.name === (isBoy ? "dave" : "choi")))

What surprised me was that

// this don't work
isBoy = false
console.log(list.find(v => v.name === isBoy ? "dave" : "choi"))

It will return "dave" instead of "choi". This was the cause of a recently very hard to find bug today. Can anyone elucidate what is going on here and why this is expected behavior?

Why does the parenthesis matter? What should I read up on to understand this better? Is this an order of operations thing? My javascript IDE linter did not complain or warn about this which it usually does when vague order of operations stuff.

What I tried

I tried searching for SA questions similar to mine that might shed light on this problem but didn't find anything that explained what I was seeing.

CodePudding user response:

The problem is operator precedence. Comparison operators have higher precedence than than ternary (since it's common to use comparisons in the condition), so your code is interpreted as:

list.find(v => (v.name === isBoy) ? "dave" : "choi")

You need to add parentheses to get what you intend:

list.find(v => v.name === (isBoy ? "dave" : "choi"))

CodePudding user response:

Well,

You are right, its because of the order javascript is executed,

v.name === isBoy ? "dave" : "choi")

This is the equivalent of

if ( v.name === isBoy ) {
  return "dave"
} else {
  return "choi"
}

CodePudding user response:

Part of the issue is that the function inside of .find() needs to return a boolean value. Your first two examples do not return boolean values - they return 'dave' or 'choi' instead of true or false. The computer is then interpreting whichever the output is as truthy and you .find() query will always return the first value of the list. Changing you code to console.log(list.find(v => v.name === (isBoy ? "dave" : "choi"))) works because the function inside of .find() will always return a boolean value - if isBoy===true it will return v.name==="dave", if not it will return v.name==="choi".

  • Related