【问题标题】:Atypical uses for Javascript's ++ and -- operatorsJavascript 的 ++ 和 -- 运算符的非典型用途
【发布时间】:2011-12-24 22:06:20
【问题描述】:

如果我从 Crockford 的“Javascript: The Good Parts”中没记错的话,他赞成使用 ++ 或 -- 运算符,但我也倾向于回忆他没有提供反对他们的特别有力的论据。

下面是这些运算符的使用,我发现它们有助于使我的代码尽可能简洁,特别是在处理返回 -1 的函数/方法时,当 0 是第一个可能的有效返回值(以及正整数) .我会对 ++ 和/或的其他非典型用法感兴趣——它们强烈支持在有意义时使用这些运算符。

我确实认为这是Why avoid increment ("++") and decrement ("--") operators in JavaScript? 的重复,而是它的必然结果:何时避免它们,而是利用它们为你带来优势。当然,我可能会弄错,并且可能有某种原因我没有想到为什么以下内容充满危险,尽管在我看来很优雅——如果我错过了以下内容的次优,我我也想知道

var substrIdx = str.indexOf(substr);
if (++substrIdx) {
  doSomething(--substrIdx);
}

【问题讨论】:

  • 看过 Crock 几次演讲后,我很确定我可以准确地想象他对那个例子的反应 :-)
  • 您的示例不太合理:substr() 返回一个字符串,而不是索引;它适用于indexOf()。但无论如何,虽然我一般喜欢递增和递减运算符,但我不喜欢这种用法,因为它更难阅读。任何其他人看到您的代码都必须停下来思考它是如何工作的(尤其是如果您不包含注释),而 if (substrIdx != -1) 是显而易见的。
  • Crockford 声明“我们不需要专门的运算符来添加一个对象”。我同意。
  • P.S.如果在使用substrIdx 的 if 块之后有代码怎么办 - 目前该值仅在 if 评估为 true 时才会更改回来。更一般地说,虽然我们不需要需要一个专门的运算符,但它确实存在并且每个人都知道它的含义,那么为什么不使用它(但不要以混淆代码的方式)?
  • Crockford 关于不需要这些是正确的。事实上,如果不是因为 PDP-8 有前置和后置增量指令,C 就永远不会有,而且没有任何 C 派生语言(ie,一切都在除了 LISP 方言和 COBOL 之外的当前使用)也可以。

标签: javascript operators increment decrement pre-increment


【解决方案1】:

如果我遗漏了以下内容的次优之处,我也想知道

var substrIdx = str.indexOf(substr);
if (++substrIdx) {
  doSomething(--substrIdx);
}

这是次优的。这会让人类感到困惑,需要通过浏览器传送更多代码,并且需要解释器在运行时完成更多工作。

有人试图弄清楚它是什么,必须在代码中的不同点对substrIdx 的状态进行推理——“它在这里遵守indexOf 的合同,但它比indexOf,在if 之后与substr 没有明确的关系。”。

也长于

var substrIdx = str.indexOf(substr);
if (substrIdx>=0) {
  doSomething(substrIdx);
}

缩小器更难缩小,因为substrIdx 不再是单个分配var。 一个好的缩小器会将后者变成类似

var substrIdx = str.indexOf(substr);
substrIdx<0||doSomething(substrIdx);

但很少有人会承担不必要的任务。他们在closure compiler 下比较不错:

var a=str.indexOf(substr);++a&&doSomething(--a)

var a=str.indexOf(substr);a>=0&&doSomething(a)

因为闭包编译器错过了将a&gt;=0&amp;&amp;转为a&lt;0||的机会,但自增自减还是比较长。

【讨论】:

  • 您的示例以更清晰的方式显示了 OP 的代码实际上在做什么。另外,在 OP 的示例中,substrIdx 将比调用indexOf 后大一,这可能不是有意的
【解决方案2】:

我认为可以接受的唯一情况是增量的结果没有被存储,因此它是前增量还是后增量都没有关系,并且不会成为错误的来源。

 var j=0;
 // These three examples are OK in my mind
 for (var i=0; i < 20; i++) {
    doSomething()
 }

 while ( i < 100) {
   if (someTest()) {
      j++;
   }      
   i++;
 }

【讨论】:

  • 请在投反对票时发表评论!我知道这不是非典型的,但这是我认为安全的唯一用途
  • 不是反对者,但也许他们投了反对票,因为您没有真正解释为什么其他用例不好(除了笼统的“错误来源”)。
【解决方案3】:

嗯,那肯定是“非典型”。这也是“聪明”。在“男孩,我希望我永远不必支持这样编写的代码”的“聪明”脉络。

代码应该是可读的。我们花在阅读代码上的时间比编写代码要多得多。这不是。

【讨论】:

  • 不要引发语言战争,但这就是我不喜欢 Perl 的原因。只写代码的机会太多,我认为这就是这个例子所展示的。
  • 好吧,至少我的聪明才智在几行之内。但回想起来,我全心全意地同意:我的代码很烂!唯一可以挽救的是将它用作面试问题:重新编写这段代码!
  • @GeorgeJempty:如果你喜欢在面试中欺骗别人,那就用它吧,我拒绝为一个试图提出棘手问题的地方工作。我更喜欢提出有意义的问题并了解他们的思考过程
  • 这不是欺骗人。您需要了解您的运营商:即使他们被认为是次优的,您也会在野外遇到他们。你还需要知道如何重构代码,这似乎是一个非常简单的例子:这里有六个人已经成功了。我认为您可能会排除不了解这些运算符和/或无法在改进代码方面做出体面尝试的人,或者至少不具备 String 方法(例如 indexOf)的基本知识
【解决方案4】:

简洁与可读性或可维护性不同,优雅在维护者眼中。您发布的代码对我来说似乎不必要地不透明。

在过去的几十年里,我对并非立即显而易见的代码产生了强烈的反感,即使显而易见的方法需要更多的代码。如果多人参与其中,隐式代码和魔术代码几乎总是难以维护。

具体评论:我不明白为什么您认为您的代码比以下更简洁、优雅或可读性:

var substrIdx = str.indexOf(substr);
if (substrIdx >= 0) {
  doSomething(substrIdx);
}

它的效率也有点低,因为您要执行两个操作和一个比较,而不仅仅是一个比较。此外,您将整数误认为是布尔值,从维护的角度来看,这几乎总是一个坏主意。

最后,正如下面提到的,您正在阻碍 Javascript 最小化程序,从最后简洁的角度来看,用户唯一关心的是页面加载速度......

【讨论】:

    猜你喜欢
    • 2011-08-08
    • 2010-09-28
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多