【问题标题】:Is checking for true explicity bad by design?检查真正的明确性是否设计不好?
【发布时间】:2011-06-11 17:20:36
【问题描述】:

显式检查布尔值是否被认为是不好的。做一个简单的if(success)会更好吗?

我看到过各种笑话,说 if (someBoolean === true) 在强类型语言中是可怕的代码,但在弱类型语言中也被认为不好?

这适用于任何对 if 语句进行类型强制的弱类型语言。

一个具体的例子是:

var onSuccess = function (JSONfromServer) {
    // explicitly check for the boolean value `true`
    if (JSONfromServer === true) {
         // do some things
    }
}

// pass it to an ajax as a callback
doSomeAjax(onSuccess);

[编辑]

在这种特殊情况下,成功变量是从服务器返回的任何有效 JSON。所以它可以是任何东西。如果它的布尔值为真,那么就成功了。如果它是一些错误处理对象,那么它将被处理。如果是其他事情,那么它可能会被悄悄地处理。

问题是让服务器以 JSON 格式返回 true 并检查处理操作成功情况的好方法。

不过,我想避免特定于 JavaScript 和 AJAX。

【问题讨论】:

    标签: javascript weakly-typed


    【解决方案1】:

    使用 Javascript 值得了解的是,除了布尔值 true 和 false,值可以是 truthyfalsy

    考虑:

    if (false)     // evaluates to false.
    if (0)         // evaluates to false, 0 is falsy.
    if ("")        // evaluates to false, empty strings are falsy.
    if (null)      // evaluates to false, null values are falsy.
    if (undefined) // evaluates to false, undefined values are falsy.
    if (NaN)       // evaluates to false, NaN is falsy.
    

    对象的所有其他值都是真实的。

    如果真值和假值导致逻辑错误,则应考虑明确使用===!== 运算符以确保按类型和值比较对象。

    【讨论】:

      【解决方案2】:

      我自己对此有两种看法。

      一方面,您发布的代码示例很好,因为 Javascript 处理类型强制的方式。只要successtruthy,一个简单的if (success) 就会进入if 块——例如一个非空字符串就可以了。三等号保证 success 确实是布尔值 true,这比使用较短版本(可能是您想要的版本)得到的保证更强。

      但是,如果您需要这个 - 即您不知道 success 是布尔值、字符串还是整数 - 我会说这本身就是一种代码味道.无论您如何进行比较,我总是会与一个不可避免地成为布尔值的变量进行比较;此时,使用哪种比较形式并不重要,因为它们是等效的。事实上,我什至会像这样引入一个“冗余”变量:

      var successCount = items.size(); // or some other way to get an integer
      var success = successCount > 0;
      if (success) {
         ...
      }
      

      所以,嗯,是的。我认为没有人会真正抱怨=== 在比较中的(显式)使用,因为它的功能差异。但出于同样的原因,如果您明确使用布尔 success 标志,那么我认为也不应该有人抱怨短样式。

      (关于你的第一句话,我认为在动态类型语言中显式检查布尔值 true 并不是坏事,如果该值实际上是你想要的。当静态类型已经约束变量时,它只是多余的是一个布尔值。)

      【讨论】:

      • 在这种特殊情况下,ajax 调用将返回一些 JSON 数据,这些数据要么是布尔值 true,要么是某种错误处理对象。我想最好检查错误对象并处理它,然后让true case 成为 else 块。
      • +1 指出可以返回 true 真实值的函数是代码异味。
      • 或者更清晰的if (items.size() > 0) { ... }
      【解决方案3】:

      通常,您希望布尔变量名称如下:

      success, enabled, pass
      

      具有真正的价值。所以

      if(success) //or
      
      if(enabled) //or
      
      if(pass) //or
      
      if(enabled) //or
      

      是可以理解和逻辑可读的。但是,如果您有以下变量:

      result, status, port1.bit7
      

      最好写:

      if(result == true) //or
      
      if(status == false) //or
      
      if(port1.bit7 == true)
      

      因为这样比下面的例子更容易理解:

      if(result)
      {
        ....
      }
      

      可读性就是可维护性。

      【讨论】:

        【解决方案4】:

        会出什么问题?没错,什么都没有。在最好的情况下,你的函数什么都不做。这比将一些随机参数接受为true 更好。

        如果你一直使用true,那么你也应该明确地检查它。

        虽然我肯定支持 Python 中的 if foo:,但这里有一个很大的不同,那就是最终一些随机的 jQuery 程序员可能会想“哦!它也适用于字符串和new Boolean()" 并使用它。

        关于 Sean 使用 !! 的建议,这实际上取决于您是否只想接受布尔值或任何真实的值。不过,对于一个干净的 API,我只接受布尔值。

        【讨论】:

          【解决方案5】:

          要添加到这个对话中,sessionStorage 和 localStorage 变量今天只能存储为字符串,所以如果你使用:

          sessionStorage.setItem('completed',true);
          

          它实际上将被转换为字符串并存储为“真”。 我见过很多人编写方法和转换来操作这个值,以便他们可以使用一个使用布尔值的 if 语句,其中一个简单的

          if sessionStorage.getItem('completed') === 'true';
          

          在我看来就足够了,而且完全清晰易读。

          【讨论】:

            【解决方案6】:

            我读过很多关于 JavaScript 的文章,但我从未见过有人说 if(success) 是一种不好的做法。我会做。您确定 success 参数将始终为布尔值吗?现在,如果这会变成其他东西,你就必须编辑这个函数。但是,如果您只使用if(success),它会适用于其他“真实”和“虚假”值,例如字符串与空字符串,或 1 与 0。

            如果您想将该参数的任何内容转换为其布尔值,您可以对其进行双重否定:!!success;但在这样的条件中,这不是必需的。

            【讨论】:

            • 成功参数是一个任意对象。
            【解决方案7】:

            是代码异味还是语言异味,还是实现细节还是约定问题?

            真的,看情况吧。

            将所有错误值和所有真实值放入一个桶中可以简化事情,直到差异很重要,无论是糟糕的代码设计还是因为某些原因确实很重要。

            同样,Hoare 为发明 null 引用表示歉意,正如我所见,这与这个真实问题的根源一样接近。 JavaScript 的设计只是通过添加更多真实值来混淆这个问题,导致许多人只是提倡显式检查以避免难以追踪的错误(Douglas Crockford)。 JavaScript 社区已经接受了语言本身,有点卡住了。 Python 核心团队主张相反,因为语言设计似乎旨在简化事物,而不是混淆它们,并且核心团队仍在计划改变语言。随着时间的推移,无论是约定还是语言设计,小而迭代的更改是大改进的本质。

            两者都是针对其特定情况的好策略。我并不是说这是唯一的改进来源,但这是目前主要的改进来源。

            例如 TrueFalse 实际上是 Python 中 int 的子类,特别是 0 和 1。这有几个设计好处。然后 PEP8 提倡宁愿做

            if a_reference:
                pass
            

            None 真正需要在 Python 中使用的唯一一次是在指定可选参数时。

            def foo(bar=optional): # NOTE I made up this idealistic construct
                """Looks good at the surface"""
                pass
            
            def foo(bar=None):
                """But this is clear to the programmer"""
                pass
            

            JavaScript 隐含地将所有变量都设为可选:

            function foo(x, y, z) {
                // Certainly not clear to the programmer.
            }
            

            Crockford 提倡明确地检查事物以尝试增加语言的清晰度。

            if (foo === undefined) {
                // pass
            }
            

            基本上,JavaScript 添加了 Null Reference #2,称为 undefined。我也觉得有趣的是,编程社区对 JavaScript 语言的考虑如此之差,他们认为增加使用 CoffeeScript、GWT、Pyjamas 之类的复杂性是一个公平的权衡,只是为了拥有更好的客户端语言。当然,我不同意增加的复杂性,但遗憾的是,有些人可能会受益,至少是暂时的,并且可以更快地完成手头的工作,而不是处理 JavaScript。

            不过,从长远来看,我确实认为这是一个愚蠢的决定。

            【讨论】:

              【解决方案8】:

              对我来说,最好最简单的解决方案是:

              var isTrue = /^true$/.test( 'true' );    // true
              var isTrue = /^true$/.test( 'false' );   // false
              var isTrue = /^true$/.test( true );      // true
              var isTrue = /^true$/.test( false );     // false
              var isTrue = /^true$/.test( ' true ' );  // false
              var isTrue = /^true$/.test( '' );        // false
              var isTrue = /^true$/.test( 'prueba' );  // false
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-04-21
                • 2011-01-02
                • 2016-05-17
                • 1970-01-01
                相关资源
                最近更新 更多