2
function ord(n) {
  var sfx = ["th","st","nd","rd"];
  var val = n%100;
  return n + (sfx[(val-20)%10] || sfx[val] || sfx[0]);
}

The part at the end, (sfx[(val-20)%10] || sfx[val] || sfx[0]); Does this kind of evaluation have a particular name in javascript? Could someone tell me what that is called so I can learn how to use them, trying to figure out how this code works.

THANKS

5 Answers5

3

It's just a series of Logical OR operators. But, as these operators are short-circuited and don't force boolean coercion, they can be used for "defaults" or "alternatives" as they'll return the first truthy value (anything other than undefined, null, NaN, 0, "", or false) between them:

console.log(1 || 2 || 3); // 1
console.log(0 || 2 || 3); // 2
console.log(0 || 0 || 3); // 3

Or the last falsy value, if none were truthy:

console.log(false || 0 || null); // null

The line return n + (sfx[(val-20)%10] || sfx[val] || sfx[0]); can be elongated to:

if (sfx[(val-20)%10]) {
    return n + sfx[(val-20)%10];
} else if (sfx[val]) {
    return n + sfx[val];
} else {
    return n + sfx[0];
}
Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199
  • If this is correct, then this is absolutely horrible. The **logical**-OR operator can evaluate to values that aren't of boolean type? – Oliver Charlesworth Feb 20 '12 at 00:18
  • @Jordan Always forget about `NaN`. Thank you. :) – Jonathan Lonowski Feb 20 '12 at 00:18
  • @Oli: Yes; the logical `OR` operator evaluates to the first truthy operand, or the second operand if neither are truthy. – icktoofay Feb 20 '12 at 00:19
  • Absolutely Oli. The result is the same: if you tested the result for truthfulness, you'd still get either a true or a false. – Chris Subagio Feb 20 '12 at 00:19
  • Thank you very much, and great way to show how this works. I initially thought this was a ternary operator for JS. –  Feb 20 '12 at 00:20
  • @OliCharlesworth I think you might need to look up typing in Javascript :P From MDN: "JavaScript has a boolean type, with possible values true and false (both of which are keywords). Any value can be converted to a boolean according to the following rules: false, 0, the empty string (""), NaN, null, and undefined all become false all other values become true" https://developer.mozilla.org/en/A_re-introduction_to_JavaScript#Other_types – Sam Giles Feb 20 '12 at 00:21
  • @ChrisSubagio: Wow. I don't use or know Javascript, but even so, that is completely unintuitive to me. – Oliver Charlesworth Feb 20 '12 at 00:21
  • @SamGiles: I'm aware that various types can be implicitly converted to boolean, but I had thought it safe to assume that a logical operator would return a boolean type! – Oliver Charlesworth Feb 20 '12 at 00:22
  • @OliCharlesworth Oh I see what you mean, I gues it isn't completely logical. You see a lot of `var a = argument || {};` To initialise a possible undefined argument I guess I'm just used to it. – Sam Giles Feb 20 '12 at 00:26
  • @OliCharlesworth heh you're looking for logic in javascript? Sure the language is as capable as any other but also uncommon in it's choice of language features [and how it implements them, IE prototype inheritance]. – Jordan Feb 20 '12 at 00:28
  • @OliCharlesworth I'm afraid not. Logical operators don't coerce their operands to booleans. Though you can do so yourself with the so-called "double-not" -- `!!` (http://stackoverflow.com/a/784946/15031). – Jonathan Lonowski Feb 20 '12 at 00:31
  • 1
    Strictly speaking though, the interesting behavior here isn't short circuiting: that specifically refers to the fact that further evaluation of logical expression is terminated as soon as the conclusion is determined. I.e. `getTrueValue() || getFalseValue()` won't actually call `getFalseValue()` at all, as the or operator just needs one of them to be true. For the OP's question, it's the JS quirk about returning the actual value, rather than coercing to a boolean that's the answer; the short circuiting can be viewed as a desirable optimization: i.e. bail on the first good result. – Chris Subagio Feb 20 '12 at 00:44
  • @ChrisSubagio Good point. Updated to add that logical operators "*don't force boolean coercion*" as part of the explanation. – Jonathan Lonowski Feb 20 '12 at 00:50
1

If you are referring to the use of ||, it is called short-circuit evaluation.

John Pick
  • 5,562
  • 31
  • 31
1

Two things going on in there.

The array index is being calculated inline. If you're unfamiliar with %, it the mathematical modulo operator: i.e. it's saying "subtract 20 from val and take the remainder when divided by 10", or subtract 10 and just take the last digit in decimal.

The x || y || z structure is about taking the first non falsy value: the || operator in javascript has the odd property of returning the first non false value, not necessarily the actual value true. To wit:

3 || 5 returns 3

0 || 5 returns 5

false || 5 returns 5

So what the code is doing is saying, "take the first non falsy number of these three calculations", which given that the first two may access values outside of the declared array items (and so return "undefined") actually means, "try the first two calculations. If they fail, default to returning 'th' "

Chris Subagio
  • 6,099
  • 1
  • 15
  • 7
0

It uses the left to right evaluation to assign the value you want,

if the 1st term evaluates to undefined, it eveluates the second, and so on.

so in the example its used to get the right suffix for dates by the look of it.

its used instead of nesting lots of if's.

Dampsquid
  • 2,456
  • 15
  • 14
0

It is a way to get the first valid statement to execute.
If the statement is invalid it will move to the next, left to right. the 0th array element IS valid since it is defined so you know you always have some sort of valid output if nothing else that's why the last statement has to be in there sfx[0]

Jordan
  • 2,708
  • 4
  • 22
  • 35