一、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. atitit.避免NullPointerException 总结and 最佳实践 o99

    atitit.避免NullPointerException 对于返回集合的方法很简单,只需要返回空的集合就可以了,而不是null. 1 一种可选办法就是不使用空返回值,而是空对象模式: 1 直接抛出e ...

  2. Linux初学 - 安装及网络配置

    安装版本 CentOS-6.4 虚拟机  vmware workstation 12 配置 网络配置 检查网络设置是否成功 如果网络配置文件检查没有问题,配置完成后网络仍然ping不同 1.检查虚拟机 ...

  3. iOS开发-UITableView滑动视差

    视差滚动是指让多层背景以不同的速度移动,形成立体的运动效果,在Web上应用的比较多,App中倒是见的相对比较少,主要在UITableView中的应用的比较多,尤其是当整个UITableViewCell ...

  4. React组件系统、props与状态(state)

     多个组件合成一个组件: var style = { fontSize: 20, color: '#ff0000' }; var WebSite = React.createClass({ rende ...

  5. 已知2个一维数组:a[]={3,4,5,6,7},b[]={1,2,3,4,5,6,7};把数组a与数组b 对应的元素乘积再赋值给数组b,如:b[2]=a[2]*b[2];最后输出数组b的元素。

    package hanqi; import java.util.Scanner; public class Test7 { public static void main(String[] args) ...

  6. Hello.class所在路径下, 输入命令:java Hello.class,会出现什么结果,为什么?

    所在路径下, 输入命令:java Hello.class: 因为DOS没有规定路径,所有么有在默认路径下找到Hello.class文件,导致提示 错误: 找不到或无法加载主类 Hello.class.

  7. VC多线程的用法

    .h 文件 #define WM_TEST    WM_USER + 1 class CTestThread : public CWinThread { DECLARE_DYNCREATE(CTest ...

  8. [原创]Java性能优化权威指南读书思维导图

    [原创]Java性能优化权威指南读书思维导图 书名:Java性能优化权威指南 原书名:Java performance 作者: (美)Charlie Hunt    Binu John 译者: 柳飞 ...

  9. Cocos2d-x3.x塔防游戏(保卫萝卜)从零开始(一)

    一.前提: 完成Hello Game项目的创建编译. 具体参考:Cocos2dx.3x_Hello Game项目创建篇 二.本篇目标: l  说说关于塔防游戏的想法和思路 l  实现一个简单的塔防游戏 ...

  10. iOS 7.1 UITableView添加footerView 后 最后一行分割线无法显示

    今天用故事版 遇到个奇怪的问题: 我要用 tbView(tableView)展示写信息.最后一行我要显示些文案什么的.考虑用 footerView ,开心coding ..,show下 哪里有些不对吧 ...