javascript - understanding Complex inArray ternary operator - Stack Overflow

I was just going through the inArray method code and came across the following :: inArray: function (el

I was just going through the inArray method code and came across the following ::

inArray: function (elem, arr, i) {
    var len;

    if (arr) {
        if (indexOf) {
            return indexOf.call(arr, elem, i);
        }

        len = arr.length;
        i = i ? i < 0 ? Math.max(0, len + i) : i : 0;

        for (; i < len; i++) {
            // Skip accessing in sparse arrays
            if (i in arr && arr[i] === elem) {
                return i;
            }
        }
    }

    return -1;
},

now i understand how tenary operators work , but can somebody tell me , how the below line of code really works ? is it even a ternary operator ?

i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;

or is it some kind of a new construct in JS ?

Thank you.

Alex-z.

I was just going through the inArray method code and came across the following ::

inArray: function (elem, arr, i) {
    var len;

    if (arr) {
        if (indexOf) {
            return indexOf.call(arr, elem, i);
        }

        len = arr.length;
        i = i ? i < 0 ? Math.max(0, len + i) : i : 0;

        for (; i < len; i++) {
            // Skip accessing in sparse arrays
            if (i in arr && arr[i] === elem) {
                return i;
            }
        }
    }

    return -1;
},

now i understand how tenary operators work , but can somebody tell me , how the below line of code really works ? is it even a ternary operator ?

i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;

or is it some kind of a new construct in JS ?

Thank you.

Alex-z.

Share Improve this question edited Jun 19, 2015 at 9:17 Tushar 87.3k21 gold badges163 silver badges181 bronze badges asked Jun 19, 2015 at 9:09 Alexander SolonikAlexander Solonik 10.3k19 gold badges86 silver badges185 bronze badges 4
  • the funny thing is, it can be even shorter: i = i < 0 ? Math.max(0, len + i) : i || 0; – Nina Scholz Commented Jun 19, 2015 at 11:35
  • @NinaScholz If i is omitted how does i < 0 get evaluated? – scign Commented Jul 9, 2021 at 4:34
  • @scign, i would be trow an error or undefined (here, the condition is false), depending on strict or not. – Nina Scholz Commented Jul 10, 2021 at 17:26
  • @NinaScholz the "longer" way prevents having to deal with that error. – scign Commented Jul 12, 2021 at 0:20
Add a ment  | 

7 Answers 7

Reset to default 6

Original Statement:

i = i ? i < 0 ? Math.max(0, len + i) : i : 0;

To understand it better,

i = i ? (i < 0 ? Math.max(0, len + i) : i) : 0;
//      ^                                ^

Yes, this is nested ternary operator ? :.

Following is the if else representation of the above statement, represented in if..else step by step.

if (i) {
    i = i < 0 ? Math.max(0, len + i) : i;
} else {
    i = 0;
}

It works as follow:

if (i) {
    if (i < 0) {
        i = Math.max(0, len + i);
    } else {
        i = i;
    }
} else {
    i = 0;
}

It's 2 ternary operators, nested. You can read it like this:

i = i ? (i < 0 ? Math.max( 0, len + i ) : i) : 0;

Or, pletely converted to if / else:

if(i)
    if (i < 0)
        i = Math.max(0, len + i);
    else
        i = i;
else
    i = 0;

You can shorten the if / else structure a bit:

if(i) {
    if (i < 0)
        i = Math.max(0, len + i);
} else
    i = 0;

Or:

if(i && i < 0)
    i = Math.max(0, len + i);
if(!i)
    i = 0;

This removes the redundant else i = i. In ternary statements, an else is required, but it can be omitted here.


Keep in mind that all the i = assignments you seen in these if / else statements are based on the single i = assignment in front of the ternary operator. Ternary operators on their own (a ? b : c) do not assign values to variables.

It's two ternaries nested.

Unrolling the outer layer would give us:

var x;
if (i) {
  x = i < 0 ? Math.max( 0, len + i ) : i;
} else {
  x = 0;
}
i = x;

Unwinding the inner branch, then gives us:

var x;
if (i) {
  if (i < 0) {
    x = Math.max( 0, len + i );
  } else {
    x = i;
  }
} else {
  x = 0;
}

i = x;

The x representing the temporary value which gets reassigned to i.

Parens might help (and parents or newlines should break these up, any time they are any harder than dirt-simple):

i = i ? ( i < 0 ? Math.max( 0, len + i ) : i ) : 0;

Now you can see the subexpression hiding in the middle of the true branch, of the outer ternary.

it breaks down to this in simple logic what kinda goes down in your mind when you code it. Note that this function does not catch undefineds, nan's nulls, strings, floats, booleans, bytes or whatever can be inputted that would be caught by the normal flow.

This is what I believe is the intention behind the line in simplified logic. This is kinda what goes on in my mind when I code such lines.

function calculatewhat(i) {
    if(i != 0) {/*i = i;*/ // i gets assigned and then evaluated. 
                           //If its anything but zero it's true, if its zero its false.
        if(i < 0) { // Test if its smaller than zero
          return Math.max( 0, len + i ) ; 
        }
        else { // its bigger than 0
           return i 
        }
    else { // if its 0... but you could just as wel return i 
           // instead of creating a new variable for the return since i is zero.
       return 0;
    }
}

I would have coded it instead of the nested as follows

i = i < 0 ? Math.max( 0, len + i ) : i

And to satisfy Cerbrus this is how it really works.

function calculatewhat(i) {
    if(i) { //check if its a true value. This will evaluate true also on "1", "blah",true, etc... 
             //To be typesafe you should make it an integer test. if(typeof i === 'number' && i !== 0);
        if(i < 0) { // Test if its smaller than zero This will also return true on "-20" and -20.555
          return Math.max( 0, len + i ) ; 
        }
        else { // its bigger than 0 return i. but its type can be anything but an integer, so beware.
           return i 
        }
    else { //it's not a number or its 0. 
           //We can't be sure about type so lets return 0 to i making it a valid integer.
       return 0;
    }
}

actually this is enough:

if (i < 0) {
  return Math.max(0, len + I);
}

As mentioned in other answers, this is a nested ternary. What I hope to provide here is a natural-language translation of the job this line is performing for the parent function.

i = i ? i < 0 ? Math.max(0, len + i) : i : 0;
       [------|----------------------|--]         inner ternary
   [--|----------------------------------|---]    outer ternary

Translation:

i ? ... : 0

(Outer ternary)

If an index to start searching from i is provided as a parameter to the function (this uses the fact that if the parameter is not provided then i will be "falsy") then proceed to evaluate the inner ternary and update i to the result, otherwise set i to 0.

i < 0 ? Math.max(0, len + i) : i

(Inner ternary)

If i is less than zero, return the the array length + i (which, since i is less than zero, finds the index of the element i positions from the end of the array) with a lower bound of zero; otherwise return i.


We can now see that this line permits the function to interpret a positive integer as a position from the start of the array and a negative integer as a position from the end of the array, while including an array bounds limitation on the position index and also allowing the parameter to be omitted pletely to default to the array start.

in the initial code, we have:

inArray: 
function (elem, arr, i) {

    /* [...] */
    i = i ? i < 0 ? Math.max(0, len + i) : i : 0;

    for (; i < len; i++) {
        /* [...] */
    }

    return -1;
}

so basically, this:

   i = i ? i < 0 ? Math.max(0, len + i) : i : 0;

can also mean: (provided that i = 5)

// i = 5 is same as 5 = i

if (5) {
   if (5 < 0) {
      i = Math.max(0, len + 5);
   } else {
      i = 5;
   }
} else {
   i = 0;
}

it's just an over simplified way of doing things.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744258915a4565533.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信