js 中 if(a) if(a == true) if(!!a) 的区别

如题

if(a){
    //...
}

if(a == true){
    //...
}

if(!!a){
    //...
}

问:

  • 这三种写法有什么逻辑上的区别吗?

  • 这三种写法在实际编程中各有什么好处?

阅读 15.8k
13 个回答

第一种和第三种没区别,第三种就是类型转化。
第二种是计算a==true的返回值,。
值等于是比较值的。
所以浏览器会先将运算符两边的变量/表达式的值先算出来,并转换成同类型(基本类型)的形式进行比较。
像这种比较运算符或者一些基本概念问题,我有一个推荐:
JavaScript 5
http://ecma-international.org...
JavaScript 6
http://ecma-international.org...
你可以到对应版本的JavaScript中寻找你需要的解释。
回到本题,先来看一下 == 运算符它的原理吧:

clipboard.png

这个就是浏览器在遇到 == 时采取的操作步骤,我来翻译一下是什么意思:

==运算符是这样被计算的:

1 让左引用(lref: left reference)成为正在计算的表达式左侧的值。
2 将左值(lval:left value)赋值为 GetValue(lval)。
3 让右引用(rref: right reference)成为正在计算的表达式右侧的值。
4 将右值(rval:left value)赋值为 GetValue(rval)。
5 返回执行rval == lval 抽象值比较的结果(参见 11.9.3)

那么在11.9.3,又是怎么规定abstract equality comparison 的呢?

clipboard.png

这就比较长了,但是也很详细。这就不一条一条的解释了。
至于上面有人提到的 2 == true 是false,来看看是怎么回事
直接看第七条就好了:
If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
那么结果就变成了:
2 == 1
所以就错了。。。。
当然,三种形式的优缺点我感觉是没有。。
你也可以参考别人的答案。

我个人只会用第一种方法、

理论上来讲、他们三个的结果应该是一样的

但是从代码的优雅和美观上、我选择一

第一种if(a)
a为以下值时转换为false

false
undefined
null
0
-0
NaN
""

第二种if(a==true)
true转化为1,再和a比较
第三种if(!!a)
感觉和第一种一样啊

!!用来强制转化数据为布尔类型,比如:

 return !!elements.className.match(new RegExp('(\\s|^)' + cName + '(\\s|$)'));

没有区别。。。凑字数

有区别的,楼主请看

var a = 'aaa';

if(a){
    console.log(true)
}else{
    console.log(false)
}
VM519:1 true

if(a == true){
    console.log(true)
}else{
    console.log(false)
}
VM541:1 false

个人认为,其实第三种在实际使用中,一般返回或者强制类型的时候用的比较多,就是无论a是什么类型,!!a的结果一定是 boolean 类型

新手上路,请多包涵

if(a)通常用作对象检测,在javascript里几乎所有的东西(包括各种方法在内)都可以被当作对象来对待,例如if(!document.getElemetById)return false; 可以判断浏览器是否支持该方法,如果不支持就退出,这个在平稳退化中经常用到。if(a == true)会把true强制转化1, 然后再和a进行比较,如果a的值为1,括号里表达式的值永远true,如果a不为1,括号里表达式的值是false。还有一种if(a === true)。这时候true就不会转化为1,除非a的值也为true,a也可以是表达式,值为true,否则括号里表达式的值永远false。第三中和第一种差不多。。。。

请复习有关数据类型的知识。
还有就是这么写的意图是什么?
a的数据类型不同会有不一样的语义。

靠近的第一个!表示判断真假,第二个表示将真假转换为对应的boolean

新手上路,请多包涵

看情况喽,就像1+1不一定等于2一样

新手上路,请多包涵

第一种跟第三种的区别:(直接上图)
clipboard.png
clipboard.png
注重比较图一最后一个例子与图二例子

简要说明直接问题
其实上面的回答都没回答到该问题的点子上,以下三种的比较,本质上都是接受隐式转换的判断,都是不太安全的比对,在实际场景中的时候按需使用

if(a){
  //...
}

if(a == true){
    //...
}

if(!!a){
    //...
}

楼主最该问的问题

//接受隐式转换
if(a == true){
    //code here
}

//不接受隐式转换 安全的比较
if(a === true){
    //code here
}

区别与联系

以上问题的说明

    //fn1
    function isTrue(a){
         return a == true;
    }
    
    //fn2
    function isTruth(a){
        return a === true;
    }
    
    //相同
    isTrue(true) //true
    isTrue(true) //true
        
    //不同
    isTrue(1)  // true
    isTruth(1) //false
    

以上两个例子则说明了在一些特殊的场景下可能出现的问题,现在我们来思考一个场景,我们把一个数组依次往dom对象上绑定属性,若是true则绑定,否则不绑定

    var ary = ["","1",true,1,"test"];
    //省略部分代码

假设通过js的dom操作把上面的内容绑定到下面的html代码中,我在注释中写代码示意

    <li>1</li>           // k == true # false
    <li k="1">1</li>     // k == true # true
    <li k="true">1</li>  // k == true # true     ##实际上这是我们唯一希望获得的元素
    <li k="1">1</li>     // k == true # true
    <li>1</li>           // k == true # false

实际情况我们只希望绑定 a[2] 但是我们把 a[1]、a[2]、a[3]全部绑定了

那我们该如何比对呢?

    我们比对的方式写成
    k === true 那么绑定的结果就会变成
    <li>1</li>           // k === true # false
    <li>1</li>           // k === true # false
    <li k="true">1</li>  // k === true # true     ##符合我们的预期
    <li>1</li>           // k === true # false
    <li>1</li>           // k === true # false

你理解了吗

同样if(variable)的判断也是不安全的

    function isT(a){return a?true:false}
    
    isT(1);            // true  #似乎符合我们的预期
    isT("undefined")   // true  #还符合你的预期吗
    isT(-1);           // true  #是不是还符合你的预期
    isT("0")           // true  #是不是仍旧符合你的预期

我就不一一列举了,在适合的场景,尽可能用 === 来做判断,这样可以防止意外情况的发生

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题