How to write a ternary operator (aka if) expressio

2020-02-17 08:12发布

For example, something like this:

var value = someArray.indexOf(3) !== -1 ? someArray.indexOf(3) : 0

Is there a better way to write that? Again, I am not seeking an answer to the exact question above, just an example of when you might have repeated operands in ternary operator expressions...

17条回答
戒情不戒烟
2楼-- · 2020-02-17 08:55

I think the || operator can be tailored to indexOf:

var value = ((someArray.indexOf(3) + 1) || 1) - 1;

The returned value is shifted up by 1, making 0 from -1, which is falsey and therefore gets replaced by the second 1. Then it is shifted back.

However, please keep in mind that readability is superior to avoiding repetition.

查看更多
啃猪蹄的小仙女
3楼-- · 2020-02-17 08:56

Not really, just use another variable.

Your example generalizes to something like this.

var x = predicate(f()) ? f() : default;

You're testing a computed value, then assigning that value to a variable if it passes some predicate. The way to avoid re-calculating the computed value is obvious: use a variable to store the result.

var computed = f();
var x = predicate(computed) ? computed : default;

I get what you mean - it seems like there ought to be some way to do this that looks a little cleaner. But I think that's the best way (idiomatically) to do this. If you were repeating this pattern a lot in your code for some reason, you might write a little helper function:

var setif = (value, predicate, default) => predicate(value) ? value : default;
var x = setif(someArray.indexOf(3), x => x !== -1, 0)
查看更多
成全新的幸福
4楼-- · 2020-02-17 09:04

I personally prefer two variants:

  1. Pure if, like @slebetman suggested

  2. Separate function, which replaces invalid value with default one, like in this example:

function maskNegative(v, def) {
  return v >= 0 ? v : def;
}

Array.prototype.indexOfOrDefault = function(v, def) {
  return maskNegative(this.indexOf(v), def);
}

var someArray = [1, 2];
console.log(someArray.indexOfOrDefault(2, 0)); // index is 1
console.log(someArray.indexOfOrDefault(3, 0)); // default 0 returned
console.log(someArray.indexOfOrDefault(3, 123)); // default 123 returned

查看更多
萌系小妹纸
5楼-- · 2020-02-17 09:04

A ternary is like an if-else, if you don't need the else part, why not just a single if instead..

if ((value = someArray.indexOf(3)) < 0) value = 0;
查看更多
走好不送
6楼-- · 2020-02-17 09:05

For numbers

You can use the Math.max() function.

var value = Math.max( someArray.indexOf('y'), 0 );

It will keep the boundaries of the result from 0 until the first result greater than 0 if that's the case. And if the result from indexOf is -1 it will return 0 as is greater than -1.

For booleans and boolean-y values

For JS there is no general rule AFAIK specially because how falsy values are evaluated.

But if something can help you most of the time is the or operator (||):

// Instead of
var variable = this_one === true ? this_one : or_this_one;
// you can use
var variable = this_one || or_this_one;

You have to be very careful with this, because in your first example, indexOf can return 0 and if you evaluate 0 || -1 it will return -1 because 0 is a falsy value.

查看更多
Animai°情兽
7楼-- · 2020-02-17 09:05

You're probably looking for a coalescing operator. Luckily, we can leverage the Array prototype to create one:

Array.prototype.coalesce = function() {
    for (var i = 0; i < this.length; i++) {
        if (this[i] != false && this[i] != null) return this[i];
    }
}

[null, false, 0, 5, 'test'].coalesce(); // returns 5

This could be further generalized to your case, by adding a parameter to the function:

Array.prototype.coalesce = function(valid) {
    if (typeof valid !== 'function') {
        valid = function(a) {
            return a != false && a != null;
        }
    }

    for (var i = 0; i < this.length; i++) {
        if (valid(this[i])) return this[i];
    }
}

[null, false, 0, 5, 'test'].coalesce(); // still returns 5
[null, false, 0, 5, 'test'].coalesce(function(a){return a !== -1}); // returns null
[null, false, 0, 5, 'test'].coalesce(function(a){return a != null}); //returns false
查看更多
登录 后发表回答