一、JS的且运算
记得最开始看到window.console&&console.log(123),当时知道能起什么作用但是没有深入研究,最近在研究后总算弄明白了。要理解这个,首先得明白三个知识点
第一:短路原则
这个大家都非常清楚的了,在做且运算的时候,“同真才真,一假则假”,比如
true&&true==true
true&&false==false
false&&false==false
false&&true==false

第二:JS逻辑运算中哪些为false哪些是true
在JS中,0、""、''、null、false、undefined、NaN的布尔值都是为false,其余为true---请注意我说的是“布尔值”

console.log(false==false) //true
console.log(0==false) //true
console.log(""==false) //true
console.log(''==false) //true
console.log(NaN==false) //false
console.log(null==false) //false
console.log(undefined==false) //false

但是如果经过boolean转换
console.log(Boolean(false)===false);
console.log(Boolean(0)===false) ;
console.log(Boolean("")===false);
console.log(Boolean('')===false);
console.log(Boolean(NaN)===false) ;
console.log(Boolean(null)===false) ;
console.log(Boolean(undefined)===false) ;
他们终于愉快的为false了

接着测试其他的:
console.log(Boolean([])===true);
console.log(Boolean({})===true);
console.log(Boolean({})===true);
console.log(Boolean('0')===true);
console.log(Boolean("0")===true);
console.log(Boolean(Function)===true);
console.log(Boolean(Object)===true);
以及非常少见的Infinity。console.log(Boolean(Infinity)===true);

第三:JS的且运算符(&&)的运算规则
理解了第一和第二,才能真正理解JS的运算规则,为什么这么说?
首先,JS的且运算是遵循短路原则的,
其次,&&两边的表达式最终是转换为布尔值,也就是说无论是{},[],"",NaN,undefined和null等等,毫无例外的取其布尔值,也就是取其Boolean()的值再进行对比。
接着,JS的且运算符特殊在于,它返回的是表达式的值,而不是表达式的布尔值

综合来讲,有表达式A1,A2,......An(n>=2),当进行且运算的时候,A1&&A2&&......&&An,从A1开始,
1.如果Boolean(Ai)===true,则执行Boolean(A(i+1)),(i>=1,i+1<=n)
1.1 如果Boolean(A(i+1))===false,返回A(i+1)的值
1.2 如果i+1=n返回A(i+1)的值
1.3 如果Boolean(A(i+1))===true,则重复执行步骤1
2.如果Boolean(Ai)===false,不执行Boolean(A(i+1)),(i>=1),返回Ai的值

举例如下
var a=1&&2 //返回1
var a=0&&2 //返回0
var a=1&&"test" //返回"test"
var a=""&&1 //返回""
var a=1&&undefined //返回undefined
var a=1&&null //返回null
var a=1&&[]&&"test"//返回"test"
var a=1&&[]&&undefined//返回undefined
why?
上面三个点已经涉及到了,比如var a=1&&undefined 其背后的逻辑如下
1.第一个表达式,1,不是布尔值,因此转换为布尔值Boolean(1)
2.Boolean(1)===true,因此执行下一个表达式undefined
3.undefined不是布尔值,因此转换为布尔值Boolean(undefined),Boolean(undefined)===false
4.运算符两边比较true!==false
3.返回布尔值为false的表达式的值,此例是undefined,赋值给a

再看另外一个例子,var a=[]&&"test"
1.第一个表达式,[],不是布尔值,因此转换为布尔值Boolean([])
2.Boolean([])===true,因此执行下一个表达式"test"
3."test"不是布尔值,因此转换为布尔值Boolean("test"),Boolean("test")===true
4.运算符两边比较true===true
3.因为整个求值的结果为true,那么则返回最后一个布尔值为true的表达式的值,此例是"test",赋值给a

现在,再来分析window.console&&console.log(123)

在现代浏览器中,比如chrome,因为JS引擎实现了console,并且存在console.log这个属性,所以
1.第一个表达式,window.console,不是布尔值,因此转换为布尔值Boolean(window.console)
2.Boolean(window.console)===true,因此执行下一个表达式console.log(123)
3.执行console.log(123),打印了123
4.console.log(123)没有返回值,或者说console.log(123)的返回值是undefined
5.undefined不是布尔值,因此转换为布尔值Boolean(undefined),Boolean(undefined)===false
6.运算符两边比较true!==false
7.返回布尔值为false的表达式的值,此例是undefined,赋值给a

如果是不支持console的浏览器,那么
1.第一个表达式,window.console,不是布尔值,因此转换为布尔值Boolean(window.console)
2.Boolean(window.console)===false,因此不执行下一个表达式
3.返回布尔值为false的表达式的值,此例是undefined

二、巧用JS的且运算
巧用且运算,的确能减少不少代码,比如window.console&&console.log(123)用if来描述的话,如下程序
if(window.console){
if(&console.log){
console.log(123)
}
}
再看一个例子,常用的根据时间显示问候语,0点到6点,显示“夜深了”;6点到12点显示“上午好”;12点到18点显示“下午好”;18点到23点显示“晚上好”
function showTime(curTime){
var greeting="";
if(curTime>=0&&curTime<6){
greeting="夜深了";
}else if(curTime>=6&&curTime<12){
greeting="上午好";
}else if(curTime>=12&&curTime<18){
greeting="下午好";
}else {
greeting="晚上好";
}
return greeting;
}
console.log(showTime(5));
console.log(showTime(9));
console.log(showTime(22));

如果用且运算符号的话
function showTime2(curTime){
var greeting=( (curTime>=0&&curTime<6) && "夜深了") || ( (curTime>=6&&curTime<12) && "上午好")|| ( (curTime>=12&&curTime<18) && "下午好") || ( (curTime>=16) && "晚上好")
return greeting;
}
console.log(showTime2(5));
console.log(showTime2(9));
console.log(showTime2(22));
一行代码就搞定了一堆的if,当然,在精简代码的同时,也会降级了代码的可读性,如果要用且运算,建议写上适当的注释以提高代码的可读性。

另外,在JS中,0,"",''以及NaN的布尔值也是为false,如果程序仅仅是判断undefined和null, 用且运算的话,因为扩大了false的判断范围,会导致不可预测的BUG。
如果仅仅是判断undefined和null,还是老实的使用if吧

从window.console&&console.log(123)浅谈JS的且运算逻辑(&&)的更多相关文章

  1. 浅谈JS之AJAX

    0x00:什么是Ajax? Ajax是Asynchronous Javascript And Xml 的缩写(异步javascript及xml),Ajax是使用javascript在浏览器后台操作HT ...

  2. 浅谈 js eval作用域

    原文:浅谈 js eval作用域 就简单聊下如何全局 eval 一个代码. var x = 1; (function () { eval('var x = 123;'); })(); console. ...

  3. 浅谈JS中的闭包

    浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...

  4. 浅谈 js 字符串之神奇的转义

    原文:浅谈 js 字符串之神奇的转义 字符串在js里是非常常用的,但是你真的了解它么?翻阅<MDN String>就可以了解它的常见用法了,开门见山的就让你了解了字符串是怎么回事. 'st ...

  5. 浅谈JavaScript浮点数及其运算

    原文:浅谈JavaScript浮点数及其运算     JavaScript 只有一种数字类型 Number,而且在Javascript中所有的数字都是以IEEE-754标准格式表示的.浮点数的精度问题 ...

  6. 浅谈 js 正则字面量 与 new RegExp 执行效率

    原文:浅谈 js 正则字面量 与 new RegExp 执行效率 前几天谈了正则匹配 js 字符串的问题:<js 正则学习小记之匹配字符串> 和 <js 正则学习小记之匹配字符串优化 ...

  7. 浅谈 js 正则之 test 方法

    原文:浅谈 js 正则之 test 方法 其实我很少用这个,所以之前一直没注意这个问题,自从落叶那厮写了个变态的测试我才去看了下这东西.先来看个东西吧. var re = /\d/; console. ...

  8. 浅谈 js 字符串 trim 方法之正则篇

    原文:浅谈 js 字符串 trim 方法之正则篇 关于 trim 其实没啥好说的,无非就是去除首位空格,对于现代浏览器来说只是简单的正则 /^\s+|\s+$/ 就可以搞定了.而且支持中文空格   等 ...

  9. 浅谈 js 字符串 search 方法

    原文:浅谈 js 字符串 search 方法 这是一个很久以前的事情了,好像是安心兄弟在学习js的时候做的练习.具体记不清了,今天就来简单分析下 search 究竟是什么用的. 从字面意思理解,一个是 ...

随机推荐

  1. paip.指针 引用 c++ java的使用总结.

    paip.指针 引用  c++ java的使用总结. ///////////////一般一个变量包括下面的信息 a.地址(指针)  b.命名(引用,别名)   c.变量内容.. 指针是一个变量的地址, ...

  2. paip.花生壳 服务启动失败 以及不能安装服务,权限失败的解决

    paip.花生壳 服务启动失败 以及不能安装服务,权限失败的解决 系统win7 NewPhDDNS_1.0.0.30166.exe  作者Attilax  艾龙,  EMAIL:1466519819@ ...

  3. main方法中声明8种基本数据类型的变量并赋值

    main方法中声明8种基本数据类型的变量并赋值  char→  int→ long→ float→ double byte→ short→ 

  4. FindFriendsServer服务搭建

    本文介绍如何搭建FindFriendsServer(https://github.com/hnrainll/FindFriendsServer)所需的环境. 环境需要: Windows+Apache+ ...

  5. SQLite 批量insert - 如何加速SQLite的插入操作

    本人翻译, 原文见: http://tech.vg.no/2011/04/04/speeding-up-sqlite-insert-operations/ 我正在开发一个Android程序, 它使用S ...

  6. android: Android Notification

    Notification即通知,用于在通知栏显示提示信息. 在较新的版本中(API level  > 11),Notification类中的一些方法被Android声明deprecated(弃用 ...

  7. Oracle的sqlnet.ora与password文件试验

    先看有没有sqlnet.ora [oracle@localhost ~]$ cd $ORACLE_HOME[oracle@localhost dbhome_1]$ cd network[oracle@ ...

  8. 漫谈Puppet4

    激动人心的改进 速度,速度,还是速度 稳定性和鲁棒性的提升 全新的Parser “不变"的agent 不兼容的改动 包管理方式的变化 配置文件/目录的路径变化 其他路径变化 Director ...

  9. Java中long和Long有什么区别 (转载)

    “Long is a class. long is a primitive. That means Long can be null, where long can't. Long can go an ...

  10. Entity Framework 6.x Code Frist For Oracle 实践与注意点

    Entity Framework 6.x Code Frist For Oracle 实践与注意点 开发环境 Visual Studio.net 2015/2017 Oracle 11g/12c 数据 ...