使用改变条件内的东西的函数是不好的做法,使条件顺序依赖?

cli*_*ait 10 javascript variables conditional if-statement function

var a = 1;

function myFunction() {
    ++a;
    return true;
}

// Alert pops up.
if (myFunction() && a === 2) {
    alert("Hello, world!");
}

// Alert does not pop up.
if (a === 3 && myFunction()) {
    alert("Hello, universe!");
}
Run Code Online (Sandbox Code Playgroud)

https://jsfiddle.net/3oda22e4/6/

myFunction递增一个变量并返回一些东西.如果我在if包含它递增的变量的语句中使用这样的函数,则条件将依赖于顺序.

这样做有好有坏,为什么?

Rou*_*rge 13

无论您是否更改条件中使用的变量,条件都依赖于顺序.您用作示例的两个if语句是不同的,无论您是否使用myFunction(),它们都会有所不同.它们相当于:

if (myFunction()) {
   if (a === 2) {
     alert("Hello, world!")
   }
}

// Alert does not pop up.
if (a === 3) {
   if (myFunction()) {
     alert("Hello, universe!")
   }
}
Run Code Online (Sandbox Code Playgroud)

在我看来,代码中的错误做法不是你在条件中改变条件的操作数值,而是在一个甚至不接受这个状态改变变量的函数中暴露和操纵你的应用程序状态这一事实.参数.我们通常会尝试将函数与其范围之外的代码隔离开来,并使用它们的返回值来影响代码的其余部分.全局变量在90%的时间都是一个坏主意,随着您的代码库变得越来越大,它们往往会产生难以跟踪,调试和解决的问题.

  • 除此之外,条件的顺序依赖性有时对优化有用.我们称之为短路.我建议阅读[这个问题](/sf/ask/654101381/)的答案快速解释短路评估. (2认同)

JMP*_*JMP 6

这是不好的做法,原因如下:

  • 代码远不如构造良好的代码可读.如果稍后由第三方检查代码,则这非常重要.

  • 如果myfunction稍后更改,则代码流完全不可预测,并且可能需要更新主要文档.

  • 小而简单的更改会对代码的执行产生严重影响.

  • 它看起来很业余.


Ber*_*rgi 5

如果你不得不问,这不是一个好习惯.是的,这正是为你所提到的原因,一种不好的做法:改变逻辑运算的操作数的顺序不会影响结果,因此边一般应避免条件的影响.特别是当它们隐藏在一个功能中时.

函数是纯的(只读状态还是做某些逻辑)或者它是否会改变状态应该从它的名字中显而易见.您有几个选项来修复此代码:

  • @TiagoCoelho我同意第一个是最好的,但我不会像说"从不"那样绝对.当然`changeAndTest`不再是一个纯谓词了,但是有一些模式(尤其是循环)你在某些条件下执行`regex.match(string)`或`i - `之类的东西,我看不到编写`const ok = changeAndTest(); if(ok)...`在没有临时变量的更简洁的变体上. (2认同)

Gre*_*reg 5

MyFunction违反了一个名为Tell,Do not Ask的原则.

MyFunction改变某事物的状态,从而使其成为命令.如果MyFunction成功或以某种方式无法递增a,则不应返回true或false.它被赋予了一份工作,它必须要么试图成功,要么如果它现在发现工作是不可能的,它应该抛出异常.

在if语句的谓词中,MyFunction用作查询.

一般来说,查询不应表现出副作用(即不改变可观察的事物).一个好的查询可以被视为计算,因为对于相同的输入,它应该产生相同的输出(有时被描述为"幂等").

同样重要的是要知道这些是帮助您和其他人推理代码的准则.代码可以引起混乱,.关于代码的困惑是对bug的孵化.

有很好的模式,比如Trier-Doer模式,可以像你的代码示例一样使用,但阅读它的每个人都必须了解名称和结构发生了什么.