1

Does javascript have weird behavior returning a value from a ternary statement? Here's a function I wrote for an app which returns a value from a ternary statement:

function getFlowAmount(fromRegionName, toRegionName)
{
    return 
        _reportPeriodId === 1 ? 
        mapData[toRegionName + 'Region']['NetFlow' + fromRegionName ] : 
        mapData[toRegionName + 'Region']['NetFlowChange' + fromRegionName];
}

The function above was returning undefined even though a dev tools watch showed that a value should be returned so I rewrote the function in a more modular and verbose way like this:

function getFlowAmount(fromRegionName, toRegionName)
{
    var flowAmount = 0;
    if(_reportPeriodId === 1) flowAmount = mapData[toRegionName + 'Region']['NetFlow' + fromRegionName ];
    else flowAmount = mapData[toRegionName + 'Region']['NetFlowChange' + fromRegionName];
    return flowAmount;
}

When I rewrote the javascript function as shown above, the function started returning the expected value. So does javascript have weird behavior returning a function value from a ternary statement? Or did I make some type of syntax or logic error in my original function above?

user7066345
  • 407
  • 1
  • 4
  • 9

2 Answers2

7

It's not super intuitive, but this has nothing to do with the ternary operation. This is all about automatic semicolon insertion.

While an expression itself can span multiple lines, in JavaScript there can not be a new line between the return statement and the start of the expression. So this:

return 
    _reportPeriodId === 1 ? 
    mapData[toRegionName + 'Region']['NetFlow' + fromRegionName ] : 
    mapData[toRegionName + 'Region']['NetFlowChange' + fromRegionName];

becomes this:

return;
    _reportPeriodId === 1 ? 
    mapData[toRegionName + 'Region']['NetFlow' + fromRegionName ] : 
    mapData[toRegionName + 'Region']['NetFlowChange' + fromRegionName];

And the ternary operation is never evaluated in the first place.

To correct it, simply begin the operation on the same line:

return _reportPeriodId === 1 ? 
    mapData[toRegionName + 'Region']['NetFlow' + fromRegionName ] : 
    mapData[toRegionName + 'Region']['NetFlowChange' + fromRegionName];
David
  • 176,566
  • 33
  • 178
  • 245
  • 2
    Beat us all to it XD – Niet the Dark Absol Nov 21 '16 at 17:05
  • are there any clever workarounds for this? or does javascript unconditionally force me to put the eval expression on the first line? – user7066345 Nov 21 '16 at 17:09
  • @user7066345: I suppose you could try wrapping the expression in parentheses and just putting the first opening parenthesis on the first line. That should start the expression without drastically affecting code formatting, and should still evaluate to the same result. – David Nov 21 '16 at 17:11
  • @David that parens workaround doesn't seem to work – user7066345 Nov 21 '16 at 17:20
  • @user7066345: You sure about that? Seems to do the trick in a simplified case: https://jsfiddle.net/Laxe4jy9/ Maybe something else is wrong in your test? – David Nov 21 '16 at 17:44
1

This is because of JavaScript's automatic semicolon insertion, which treats the return as two separate statements:

function getFlowAmount(fromRegionName, toRegionName)
{
    return;
    _reportPeriodId === 1 ? 
        mapData[toRegionName + 'Region']['NetFlow' + fromRegionName ] : 
        mapData[toRegionName + 'Region']['NetFlowChange' + fromRegionName];
}

The return statement is affected by automatic semicolon insertion (ASI). No line terminator is allowed between the return keyword and the expression.


Writing the return statement without a line break right after the return keyworkd will resolve the issue:

function getFlowAmount(fromRegionName, toRegionName)
{
    return _reportPeriodId === 1 ? 
        mapData[toRegionName + 'Region']['NetFlow' + fromRegionName ] : 
        mapData[toRegionName + 'Region']['NetFlowChange' + fromRegionName];
}
TimoStaudinger
  • 34,772
  • 13
  • 76
  • 86