理解复杂的inArray三元运算符

时间:2015-06-19 09:09:05

标签: javascript ternary-operator

我刚刚浏览了inArray方法代码并遇到了以下内容:

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;
},

现在我明白了tenary运营商是如何运作的,但有人可以告诉我,下面的代码行如何真正起作用?它甚至是一个三元运算符?

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

或者它是JS中的某种新构造?

谢谢。

亚历-Z

6 个答案:

答案 0 :(得分:4)

原始声明:

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

要更好地理解它,

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

是的,这是嵌套 ternary operator ? :

以下是上述声明的if else表示形式,逐步显示在if..else中。

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

它的工作原理如下:

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

答案 1 :(得分:1)

它是嵌套的两个三元运算符。你可以这样读:

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

或者,完全转换为if / else

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

您可以稍微缩短if / else结构:

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

或者:

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

这会删除多余的else i = i。在三元语句中,需要else,但这里可以省略。

请注意,您在这些i =语句中看到的所有if / else作业均基于三元运算符前面的单i =作业。三元运算符(a ? b : c)不会为变量赋值。

答案 2 :(得分:0)

它以简单的逻辑分解为此,当您编写代码时,脑海中会出现什么样的情况。请注意,此函数不会捕获未定义的值,nan的空值,字符串,浮点数,布尔值,字节或任何可以输入的正常流量。

这就是我所认为的简化逻辑背后的意图。当我编写这样的行时,这就是我的想法。

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 = i < 0 ? Math.max( 0, len + i ) : i

为了满足Cerbrus,它的确如此有效。

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;
    }
}

答案 3 :(得分:0)

它的两个三元嵌套。

展开外层会给我们:

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

解开内部分支,然后给我们:

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

i = x;

x表示重新分配给i的临时值。

Parens可能有所帮助(父母或换行也应该打破这些,任何时候它们都比简单的更难 - >

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

现在你可以看到隐藏在外部三元的真正分支中间的子表达式。

答案 4 :(得分:0)

实际上这已经足够:

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

答案 5 :(得分:0)

正如其他答案中提到的,这是一个嵌套的三元组。我希望在这里提供的是该生产线为父功能执行的工作的自然语言翻译。

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

翻译:

i ? ...0

(外三元)

如果从 i 开始搜索的索引作为参数提供给函数(这使用了如果未提供参数则 i 将是“假的”的事实)然后继续评估内部三元并将 i 更新为结果,否则将 i 设置为 0。

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

(内三元)

如果 i 小于零,则返回数组长度 + i(由于 i 小于零,因此找到元素 i 的索引数组末尾的位置),下限为零;否则返回 i


我们现在可以看到,这一行允许函数将正整数解释为从数组开始的位置,将负整数解释为从数组末尾开始的位置,同时包括对位置的数组边界限制index 并允许完全省略参数以默认为数组开始。