在条件陈述中分配变量,良好实践与否?

Mic*_*Mao 103 javascript

一年前,我从经典的OO语言(如Java)转向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));
    }
    else return false;
}
Run Code Online (Sandbox Code Playgroud)

基本上我刚刚发现我可以在if条件语句中为一个值赋值,并立即检查赋值,就好像它是布尔值一样.

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

Mat*_*ley 110

我不推荐它.问题是,在您尝试比较值时,它看起来像是一个常见错误,但使用单个=而不是=====.例如,当你看到这个:

if (value = someFunction()) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

你不知道他们打算做什么,或者他们打算写这个:

if (value == someFunction()) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果您真的想要进行任务,我建议您进行明确的比较:

if ((value = someFunction()) === <whatever truthy value you are expecting>) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 但是,如果您正在测试返回布尔值的函数的失败/成功,则最后一个示例不起作用.换句话说,当`if(resultArr = myNeedle.exec(myHaystack)){...}`有效时,`if((resultArr = myNeedle.exec(myHaystack))=== true){...}`不是因为即使函数结果不是这样,对resultArr的赋值总是很简单.如果有人使用这个..构造,请记住先声明结果变量; 'var'在if条件语句中不合法. (4认同)
  • 您可以使用`if(!!(value = someFunction()))`,但正如您所说,问题是您不能在`if`中使用`var`,因此您要么最终创建全局,要么实现什么都没有,因为你必须在一个单独的行中声明`value`.惭愧,我真的很喜欢C++中的这种结构. (3认同)
  • @Matthew Crumley:这清楚地回答了我的问题。我不是通过分配来检查,而是检查分配后评估的值。这种理解对吗? (2认同)
  • @迈克尔:是的,这是正确的。添加比较基本上只会让你的意图更加清晰。 (2认同)

Adr*_*mew 21

我没有看到证据证明这不是好的做法.是的,它可能看起来像是一个错误,但这很容易通过明智的评论来弥补.举个例子:

if (x = processorIntensiveFunction()) { // declaration inside if intended
    alert(x);
}
Run Code Online (Sandbox Code Playgroud)

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

alert(processorIntensiveFunction());
Run Code Online (Sandbox Code Playgroud)

因为LOOKS的第一个版本不好?我不能同意这种逻辑.

  • 不要挖掘旧的评论,但我不同意你的观点.可读代码应该在不需要注释的情况下解释自己 - 在混淆代码中添加注释不是一种补救措施.至于第二部分,其中说替代方案是再次调用该函数,我认为没有人打算这样做.相反,你会做`x = processorItensiveFunction(); if(x){alert(x); }` (30认同)
  • @maksim:我喜欢可读的代码,但这并不一定意味着代码应该被愚蠢或过于冗长.在多行上传播内容并在变量之间调整值实际上可能导致更糟糕的代码.插入的代码可能会在像JS这样的弱类型/灵活语言中产生无法预料的副作用.条件语句中的赋值在javascript中有效,因为您只是询问"如果赋值有效,则执行可能包含赋值结果的操作".但实际上,在条件之前分配也是有效的,不是太冗长,而且更常用. (7认同)
  • @maksim - 在“if-else”情况下,您的解决方案也会非常不方便。考虑 - `if (condition) {...} else if (x = processorIntensiveFunction()) {alert(x)}` 你之前的 `x = processorIntensiveFunction();` 如果初始 `condition` 是浪费的努力真的。 (2认同)

Min*_*ang 13

我做了很多次.为了绕过JavaScript警告,我添加了两个parens:

if ((result = get_something())) { }
Run Code Online (Sandbox Code Playgroud)

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

  • @Michael:JSLint(http://www.jslint.com/)是一个流行的程序/库,用于检查JavaScript程序是否存在可能的错误或错误的代码. (4认同)
  • @SHiNKiROU:我怎样才能看到javascript警告?有Javascript编译器吗?或者解释器会生成某种警告?我一直使用 Firefox 控制台作为 javascript 调试,但从未看到任何类似的输出。抱歉我的经验有限。 (2认同)
  • @t3chb0t:截至 2022 年,在 JavaScript 中,不带 var|let|const 的 [= 赋值](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-assignment-operators) 是_表达_。这意味着,它可以在任何可以使用表达式的地方使用,包括在“if(...)”中。另请注意,除非变量“a”已提前声明,否则它将是**全局**。这通常不是您想要的。 (2认同)

Dan*_*ist 9

有一种情况,当你这样做时,使用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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

希望您能理解,祝您好运!


小智 6

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

“动机

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

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

是的,他的答案对于 Java 实现也有效。尽管在示例中,它并未将条件函数分配给变量。


Ben*_*tto 5

你也可以用Java做到这一点.不,这不是一个好习惯.:)

(并使用===Javascript中的类型相等.阅读Crockford的关于JS的The Good Parts一书.)

  • 啊,是的,在 Java 中它被类型检查为布尔类型。但你*可以*做 `if (foo = getSomeBoolValue()) { }` (2认同)
  • 大家好,我是作为 node.js javascript 用户来到这里的。为什么在我感到痛苦的一种情况下这不是一个好的做法: if (myvar = 'just a test') 创建一个 node.js 全局变量 myvar (https://nodejs.org/docs/latest-v12.x/​​api /globals.html#globals_global)。因此,如果您像我一样并在服务器请求处理中使用该变量(几秒钟后可能会收到其他请求等内容,请返回该变量),您可能会对得到的结果感到惊讶。因此建议是:请注意,此模式在 Node.js 中创建了一个全局变量。 (2认同)