【问题标题】:understanding Complex inArray ternary operator了解复杂的 inArray 三元运算符
【发布时间】:2015-09-05 04:55:15
【问题描述】:

我刚刚浏览了 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;
},

现在我了解了三元运算符的工作原理,但是有人可以告诉我,下面的代码行是如何工作的吗?它甚至是三元运算符吗?

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

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

谢谢。

亚历克斯-z。

【问题讨论】:

  • 有趣的是,它可以更短:i = i &lt; 0 ? Math.max(0, len + i) : i || 0;
  • @NinaScholz 如果i 被省略,i &lt; 0 如何得到评估?
  • @scign,我会抛出错误或undefined(这里,条件为假),取决于严格与否。
  • @NinaScholz “更长”的方式可以避免处理该错误。

标签: javascript ternary-operator


【解决方案1】:

声明原文:

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

【讨论】:

  • 为了迂腐,在 if 语句中没有对 i 的赋值。给定的三元组没有副作用,而它们将左侧的分配与右侧的评估相结合。在这个例子中,这 100% 没问题,但在教授三元作为概念时有点虚伪。
  • @Norguard 对!感谢您的信息
【解决方案2】:

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

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 是必需的,但这里可以省略。


请记住,您在这些 if / else 语句中看到的所有 i = 赋值都是基于三元运算符前面的单个 i = 赋值。三元运算符本身 (a ? b : c) 不会为变量赋值。

【讨论】:

  • i = i ? 开头,这还算支票吗?还是只是用一个值初始化 i ?我很难相信i = i 的计算结果为if(i){}! ,但如果是这样的话,我猜这就是js的工作方式!
  • i = i 来自三元语句中的最后一个 : i。当使用if / else 结构时,else 不是必需的。
  • if (i) ... else i = 0;(第三个灰色框)的 else 被分配给 if (i &lt; 0) 而不是外部 if。
  • 为了迂腐,在 if 语句中没有对 i 的赋值。给定的三元组没有副作用,而它们将左侧的分配与右侧的评估相结合。在这个例子中,这 100% 没问题,但在教授三元作为概念时有点虚伪。
【解决方案3】:

它以简单的逻辑分解为当您编写代码时您会想到什么。请注意,此函数不会捕获未定义、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;
    }
}

【讨论】:

  • 不,它没有,OP 的三元代码中没有return 语句。
  • 三元运算符返回值 smartass。 var x = true ? "hello" : "world"; 使 x 为真。它的回报。他想知道它做了什么。这基本上就是它的作用。它将真实值返回给受让人。
  • 如果 OP 盲目地用您的代码替换三元语句,他的函数会过早返回。变量赋值和返回值之间存在很大的区别。
  • 没错,但他想知道它是如何工作的。如果您将其发布在函数调用中,这就是它的工作原理。它有助于理解三元运算将值返回给您,就好像您正在调用函数一样。它消除了许多看似发生的魔法。我修改了我的答案以更适合您的 cmets。
  • 你忘记了i = calculatewhat(i)
【解决方案4】:

这是两个嵌套的三元组。

展开外层会给我们:

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;

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

Parens 可能会有所帮助(父母或换行符应该将它们分解,只要它们比简单粗暴更难):

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

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

【讨论】:

  • 我看不到我的代码在哪里不正确,足以证明不赞成投票。特别是在我明确定义了一个新变量来表示子表达式的值的地方,因为在提供的三元组中正好有 0 个副作用(分配给i)。很高兴纠正任何错误/疏忽,否则。
【解决方案5】:

其实这就够了:

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

【讨论】:

    【解决方案6】:

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

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

    翻译:

    i ? ... : 0

    (外三元)

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

    i &lt; 0 ? Math.max(0, len + i) : i

    (内部三元)

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


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

    【讨论】:

      猜你喜欢
      • 2017-04-11
      • 2011-09-07
      • 1970-01-01
      • 2016-07-18
      • 2021-05-27
      • 2015-09-27
      • 1970-01-01
      • 2016-05-03
      相关资源
      最近更新 更多