在 if 条件语句中分配变量,好的做法与否?

IT技术 javascript
2021-02-01 13:24:11

一年前,我从 Java 等经典 OO 语言转向了 JavaScript。在 Java 中绝对不推荐(甚至不正确)以下代码:

if(dayNumber = getClickedDayNumber(dayInfo))
{
    alert("day number found : " + dayNumber);
}
function getClickedDayNumber(dayInfo)
{
    dayNumber = dayInfo.indexOf("fc-day");
    if(dayNumber != -1) //substring found
    {
        //normally any calendar month consists of "40" days, so this will definitely pick up its day number.
        return parseInt(dayInfo.substring(dayNumber+6, dayNumber+8));
    }
    return false;
}

基本上我刚刚发现我可以在 if 条件语句中将一个变量分配给一个值,并立即检查分配的值,就好像它是布尔值一样。

为了更安全,我通常将其分成两行代码,先赋值然后检查变量,但现在我发现了这一点,我只是想知道在有经验的 JavaScript 开发人员眼中这是否是一种好的做法?

6个回答

我不会推荐它。问题是,当您尝试比较值但使用单个=而不是==or 时,这看起来像是一个常见错误===例如,当您看到以下内容时:

if (value = someFunction()) {
    ...
}

你不知道这是否是他们的本意,或者他们是否打算这样写:

if (value == someFunction()) {
    ...
}

如果你真的想就地分配,我建议你也做一个明确的比较:

if ((value = someFunction()) === <whatever truthy value you are expecting>) {
    ...
}
@riv,你说得对;如果函数返回一个布尔值——就像我在上面的评论中所说的那样——那么条件会按预期工作。但是如果函数返回一个布尔值(如我的例子),那么整个构造就有点无意义了;显然,我的想法是——从这个例子来看——该函数将返回一个数组。快速测试表明,true仅当函数返回 时true条件的计算结果为,但在所有其他情况下(包括返回数组、字符串、数字或空值时),它的计算结果为false
2021-03-19 13:24:11
你可以使用if (!!(value = someFunction())),但正如你所说,问题是你不能使用varinsideif所以你要么最终创建一个全局,要么什么都不实现,因为你必须value在单独的行中声明可惜,我真的很喜欢 C++ 中的这种结构。
2021-03-29 13:24:11
但是,如果您正在测试返回布尔值的函数的失败/成功,则最后一个示例不起作用。换句话说,while if (resultArr = myNeedle.exec(myHaystack)) {...}有效,if ((resultArr = myNeedle.exec(myHaystack)) === true) {...}因为即使函数 result 不是,对 resultArr 的赋值也始终为真。如果有人使用 this.. 构造,记得先声明结果变量;'var' 在 if 条件语句中是不合法的。
2021-04-06 13:24:11
@Matthew Crumley:这清楚地回答了我的问题。我不是通过分配来检查,而是检查分配后评估的值。这种理解对吗?
2021-04-07 13:24:11
@迈克尔:是的,没错。添加比较基本上只是让您的意图更加明确。
2021-04-11 13:24:11

我看不到任何证据表明这不是好的做法。是的,它可能看起来像是一个错误,但通过明智的评论很容易纠正。举个例子:

if (x = processorIntensiveFunction()) { // declaration inside if intended
    alert(x);
}

为什么应该允许该函数第二次运行:

alert(processorIntensiveFunction());

因为第一个版本看起来很糟糕?我不能同意这种逻辑。

如果您修复 OPC,与不同技能水平的其他开发人员合作(换句话说,您是专业人士),您会讨厌这甚至是可能的。
2021-03-24 13:24:11
不是挖掘旧评论,但我不同意您的论点。可读代码应该在不需要注释的情况下自我解释 - 为令人困惑的代码添加注释并不是一种补救措施。至于第二部分,它说另一种方法是再次调用该函数,我认为没有人打算这样做。相反,你会做x = processorItensiveFunction(); if(x) { alert(x); }
2021-03-27 13:24:11
@maksim 为什么你认为if ( ! x = anyFunction() )不可读?它不需要任何评论。
2021-03-28 13:24:11
@maksim - 在某些if-else情况下,您的解决方案也会非常不方便考虑 -如果初始是正确的,if (condition) {...} else if (x = processorIntensiveFunction()) {alert(x)} 您的先前x = processorIntensiveFunction();将是白费力气condition
2021-04-03 13:24:11
@maksim:我喜欢可读的代码,但这并不一定意味着代码应该被简化或过于冗长。将事物分散在多行上并在变量之间处理值实际上会导致更糟糕的代码。插入的代码在弱类型/灵活的语言(如 JS)中可能会产生无法预料的副作用。条件语句中的赋值在 javascript 中是有效的,因为您只是问“如果赋值有效,做一些可能包括赋值结果的事情”。但确实,在条件之前赋值也是有效的,不会太冗长,更常用。
2021-04-06 13:24:11

我做了很多次。为了绕过 JavaScript 警告,我添加了两个括号:

if ((result = get_something())) { }

你应该避免它,如果你真的想使用它,在它上面写一个评论,说明你在做什么。

使用带有 Firebug 和/或 Web Developer 扩展的 Mozilla Firefox 来检查警告。
2021-03-21 13:24:11
@Michael:JSLint ( jslint.com ) 是一个流行的程序/库,用于检查 JavaScript 程序是否存在可能的错误或错误代码。
2021-04-02 13:24:11
@SHiNKiROU :我怎样才能看到 javascript 警告?有 Javascript 编译器吗?或者解释器会产生某种警告?我一直使用 Firefox 控制台作为 javascript 调试,但从未看到任何类似的输出。抱歉我的经验有限。
2021-04-06 13:24:11
我只是在尚未if ((a = [1, 2]).length > 0) { console.log(a); }a任何地方初始化的地方尝试过它,它确实有效(很好!使使用正则表达式更容易)。这是正确的,我不需要var|const|let这里的任何东西吗?你知道我在哪里可以阅读更多关于这个技巧的信息吗?
2021-04-13 13:24:11

当你这样做时,有一种情况,使用while-loops。
读取文件时,您通常会这样做:

void readFile(String pathToFile) {
    // Create a FileInputStream object
    FileInputStream fileIn = null;
    try {
        // Create the FileInputStream
        fileIn = new FileInputStream(pathToFile);
        // Create a variable to store the current line's text in
        String currentLine;
        // While the file has lines left, read the next line,
        // store it in the variable and do whatever is in the loop
        while((currentLine = in.readLine()) != null) {
            // Print out the current line in the console
            // (you can do whatever you want with the line. this is just an example)
            System.out.println(currentLine);
        }
    } catch(IOException e) {
        // Handle exception
    } finally {
        try {
            // Close the FileInputStream
            fileIn.close();
        } catch(IOException e) {
            // Handle exception
        }
    }
}

查看while第 9 行-loop。在那里,读取新行并将其存储在变量中,然后运行循环的内容。我知道这不是 -if语句,但我想您的问题中也可以包含一个 while 循环。

这样做的原因是,当使用 a 时FileInputStream,每次调用时FileInputStream.readLine(),它都会读取文件中的下一行,因此,如果您从循环中调用它fileIn.readLine() != null而不分配变量,而不是调用(currentLine = fileIn.readLine()) != null,然后从在循环内部,你只会得到每两行。

希望你理解,祝你好运!

如果您要参考 Martin Fowlers 的书重构改进现有代码的设计然后有几种情况,这将是一种很好的做法,例如。使用函数或方法调用来断言您的案例的长复杂条件:

“动机

程序中最常见的复杂领域之一在于复杂的条件逻辑。当您编写代码来测试条件并根据各种条件执行各种操作时,您很快就会得到一个相当长的方法。方法的长度本身就是一个使其更难阅读的因素,但条件会增加难度。问题通常在于这样一个事实,即条件检查和操作中的代码会告诉您发生了什么,但很容易掩盖其发生的原因。

与任何大型代码块一样,您可以通过分解它并用以该代码块的意图命名的方法调用替换代码块来使您的意图更加清晰。> 有了条件,您可以通过对条件部分和每个备选方案执行此操作来获得更多好处。通过这种方式,您可以突出显示条件,并清楚地说明您 > 正在分支的内容。您还强调了分支的原因。”

是的,他的回答也适用于 Java 实现。尽管在示例中,它不会将条件函数分配给变量。