一、概念

与其他语言不同,在js中,逻辑运算符可以返回任何类型的数据,不仅仅是true和false。

&&和||的返回值是两个操作数的其中一个。即a&&b或者a||b返回的是要么是a,要么是b,而其他语言中返回的是true or false。

在js逻辑运算中,需要隐式的转换为boolean类型再来运算,转换规则为:

1. 对象、非零number、非空string——>true

2. 0、""、null、false、undefined、NaN——>false

具体见下表:

数据类型

转换为boolean后的值
NAN FALSE
null FALSE
undefined FALSE
Object TRUE
Function TRUE
0 FALSE 
非零的数字              TRUE
""(空字符串) FALSE
非空字符串              TRUE

因此:

a && b : 将a, b转换为Boolean类型, 再执行逻辑与, 如果结果是true返回b, false返回a
a || b : 将a, b转换为Boolean类型, 再执行逻辑或, 如果结果是false返回b, true返回第一个为true的值。

逻辑&&和逻辑||还有一个短路原则:知道了前面第一个的结果就知道最后的输出

a&&b:左操作数为假值时,返回左操作数,否则返回右操作数。
a||b:左操作数为假值时,返回右操作数,否则返回左操作数。

只要“||”前面为false,不管“||”后面是true还是false,都返回“||”后面的值。

只要“||”前面为true,不管“||”后面是true还是false,都返回“||”前面的值。

只要“&&”前面是false,无论“&&”后面是true还是false,结果都将返“&&”前面的值;

只要“&&”前面是true,无论“&&”后面是true还是false,结果都将返“&&”后面的值;

同样对于多个操作数的情况:

a||b||c||d:若结果为true则返回第一个true值,若结果为false则返回最后一个操作数。eg:var a = “” || null || 3 || 2 -> var a = fasel || false || true || true 结果为true 则返回第一个true,即是3

a&&b&&c&&d:若结果为false则返回第一个false,若结果为true则返回最后一个操作数。eg:var b = 2&&null&&1&&0 -> var b = true&&false&&true&&false结果是false 则返回第一个false 即是null

二、理解

“&&”和“||”运算符均可以从三个不同的层次来逐步理解:

以“&&”为例解释如下:

(1)最简单的第一层理解是,当操作数都是布尔值的时候,“&&”对两个值执行布尔与(AND)操作,只有在第一个操作数和第二个操作数都是true的时候,它才返回true。如果其中一个操作数是false,它返回false。

(2)“&&”的操作数并不一定是布尔值。于是对“&&”的第二层理解是,“&&”可以对真值和假值进行布尔与(AND)操作。如果两个操作数都是真值,那么返回一个真值;否则,至少一个操作数是假值的话,则返回一个假值。在JavaScript中任何希望使用布尔值的地方,表达式和语句都会将其当做真值或假值来对待,因此实际上“&&”并不总是返回true和false。

(3)第三层理解,运算符首先计算左操作数的值,即首先计算“&&”左侧的表达式。如果计算结果是假值,那么整个表达式的结果一定也是假值,因此“&&”这时简单地返回左操作数的值,而并不会对右操作数进行计算。反过来讲,如果左操作数是真值,那么整个表达式的结果则依赖于右操作数的值。如果右操作数是真值,那么整个表达式的值一定是真值;如果右操作数是假值,那么整个表达式的值一定是假值。

  理解如下例子对于理解“&&”可能不会去计算右操作数的情况至关重要,在以下示例代码中,变量p的值是null,而如果计算表达式p.x的话则会抛出一个类型错误异常。但是示例代码使用了“&&”的一种符合语言习惯的用法,因此只有在p为真值(不能是null或者undefined)的情况下才会计算p.x。反过来,我们一般需要用某个对象p中的某个元素时,为了严谨也应该先对其是否存在进行判断。

  1. var o = { x : 1 };
  2. var p = null;
  3. o && o.x // =>1:o 是真值,因此返回值为o.x
  4. p && p.x //=>null: p是假值,因此将其返回,而并不去计算p.x

三、使用场景

1.||运算符最常用的方式是用来从一组备选表达式中选出第一个真值表达式,即从一系列值中获取第一个true值。

  1. // 如果max_width已经定义了,直接使用它;否则在preferences对象中查找max_width;如果没有定义它,则使用一个写死的常量
  2. var max = max_width || preferences.max_width || 500;

2.判断某个元素是否存在时:if(attr)写成if(!!attr)更加严谨。

!!的作用是把一个其他类型的变量转成的bool类型。eg:

  1. typeof 5//"number"
  2. typeof !!5//"boolean"

3.对函数中的参数赋以默认值:a=a||"defaultValue";

例如当a不存在或不合法时为其赋默认值,比起如下两种写法:

  1. if(!a){
  2.   a="defaultValue";
  3. }
  1. if(a==null||a==""||a==undefined){
  2.   a="defaultValue";
  3. }

用||一句话就可以实现,简单又优雅:

  1. a=a||"defaultValue";

4.利用&&的短路特性有条件的执行代码

(1)在回调中,经常这样写:callback&&callback(),先判断 callback 是不是存在,存在才执行,这样写更加严谨,如果直接写 callback(); 当callback不存在时代码就会报错。

(2)又或者常见的条件语句:if (a==b) stop();如果用&&来实现即为:(a==b)&&stop();

(3)判断某个对象存在再取值:p && p.x

应用举例:
如图:
假设对成长速度显示规定如下:
成长速度为5显示1个箭头;
成长速度为10显示2个箭头;
成长速度为12显示3个箭头;
成长速度为15显示4个箭头;
其他都显示都显示0个箭头。

(1)最容易想到也最常规的方法:if-else

  1. var add_level = 0;
  2. if(add_step == 5){
  3. add_level = 1;
  4. }
  5. else if(add_step == 10){
  6. add_level = 2;
  7. }
  8. else if(add_step == 12){
  9. add_level = 3;
  10. }
  11. else if(add_step == 15){
  12. add_level = 4;
  13. }
  14. else {
  15. add_level = 0;
  16. }

(2)switch方法:

  1. var add_level = 0;
  2. switch(add_step){
  3. case 5 : add_level = 1;
  4. break;
  5. case 10 : add_level = 2;
  6. break;
  7. case 12 : add_level = 3;
  8. break;
  9. case 15 : add_level = 4;
  10. break;
  11. default : add_level = 0;
  12. break;
  13. }

(3)而如果用&&和||就会超级简单:

  1. var add_level = (add_step==5 && 1) || (add_step==10 && 2) || (add_step==12 && 3) || (add_step==15 && 4) || 0;

优化为:

  1. var add_level={'5':1,'10':2,'12':3,'15':4}[add_step] || 0; //对象取值有两种方式,一种object.key,一种是object[key],此处为法二

特别是如果需求改成:
成长速度为>12显示4个箭头;
成长速度为>10显示3个箭头;
成长速度为>5显示2个箭头;
成长速度为>0显示1个箭头;
成长速度为<=0显示0个箭头。
那么用switch实现起来也很麻烦了,而同样用&&和||只要如下即可。

  1. var add_level = (add_step>12 && 4) || (add_step>10 && 3) || (add_step>5 && 2) || (add_step>0 && 1) || 0;

注:与&&和||不同,!操作符的行为与C、Java等语言是一致的,只返回boolean值(true或false)。

参考:

http://www.cnblogs.com/yanayana/p/7079345.html

全面解析JavaScript中“&&”和“||”操作符(总结篇)

JavaScript中“&&”和“||”操作符的意义,深入理解和使用场景的更多相关文章

  1. 全面解析JavaScript中“&&”和“||”操作符(总结篇)

    1.||(逻辑或), 从字面上来说,只有前后都是false的时候才返回false,否则返回true. ? 1 2 3 4 alert(true||false); // true alert(false ...

  2. javascript中的操作符详解1

    好久没有写点什么了,根据博主的技术,仍然写一点javascript新手入门文章,接下来我们一起来探讨javascript的操作符. 一.前言 javascript中有许多操作符,但是许多初学者并不理解 ...

  3. JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的区别

    ECMAScript将对象的属性分为两种:数据属性和访问器属性.每一种属性内部都有一些特性,这里我们只关注对象属性的[[Enumerable]]特征,它表示是否通过 for-in 循环返回属性,也可以 ...

  4. [转] JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的区别

    ECMAScript将对象的属性分为两种:数据属性和访问器属性.每一种属性内部都有一些特性,这里我们只关注对象属性的[[Enumerable]]特征,它表示是否通过 for-in 循环返回属性,也可以 ...

  5. Javascript中void操作符

    Javascript中void是一个操作符,该操作符指定要计算一个表达式但是不返回值. void操作符用法格式如下:1.javascript:void (expression)2.javascript ...

  6. JavaScript中对null和undefined的理解

    前沿: 今天工作中遇到了监视一个变量是undefined,结果判断写的是==null 返回值是true,这个结果引起了我对这两个东西的兴趣. 查询了相关的文章理解并测试了.发现有以下特点: 1.广义上 ...

  7. JSON 在JavaScript 中的应用及自己的理解

    [对象和json]JSON:JavaScript 对象表示法(JavaScript Object Notation).JSON 是存储和交换文本信息的语法.类似 XML.JSON是一种数据格式,不是一 ...

  8. javascript中new操作符的原理

    javascript中的new是一个语法糖,对于学过c++,java 和c#等面向对象语言的人来说,以为js里面是有类和对象的区别的,实现上js并没有类,一切皆对象,比java还来的彻底 new的过程 ...

  9. javascript中的prototype和__proto__的理解

    在工作中有时候会看到prototype和__proto__这两个属性,对这两个属性我一直比较蒙圈,但是我通过查阅相关资料,决定做一下总结加深自己的理解,写得不对的地方还请各位大神指出. 跟__prot ...

随机推荐

  1. 初始CSS模板

    /*开始 初始CSS模板 开始*/ body, div, address, blockquote, iframe, ul, ol, dl, dt, dd, li, dl, h1, h2, h3, h4 ...

  2. Spring学习(3):IOC基础(转载)

    一. IoC是什么 Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象 ...

  3. DNS递归查询与迭代查询

    注:一般TCP/IP的应用层或者OSI的会话.表示.应用层把数据称为数据或者信息,到了传输层把数据称为报文,到了最底层就是比特流了也就是字节流 DNS递归查询与迭代查询   基础知识 1.域名系统 2 ...

  4. 【python 3.6】如何将list存入txt后,再读出list

    今天遇到一个需求,就是将一个list文件读取后,存入一个txt配置文件.存入时,发现list文件无法直接存入,必须转为str模式. 但在读取txt时,就无法恢复成list类型来读取了(准确地说,即使强 ...

  5. HP Vitrual Connect 配置快速参考

    使用任意浏览器,在地址栏输入VC的管理地址(如果不知道VC的管理地址请从OA中进入) 输入用户名和密码登入VC,验证成功后将进入VM的配置向导 点击"Next"继续,将先进行Dom ...

  6. JAVA学习笔记--策略设计模式与适配器模式

    一.策略设计模式 创建一个能够根据所传递对象的不同而具有不同行为的方法被称为策略设计模式:这类方法包含所要执行的算法中固定不变的部分,而“策略”包含变化的部分.策略就是传递进去的参数对象,它包含要执行 ...

  7. 01_基于TCP的循环为同一个客户端下载文件的下载器

    原版: TCP分为客户端(client)和服务器(server),每次服务器只能为客户端提供一次的下载服务. 改良版: TCP分为客户端(client)和服务器(server), (1)每次服务器能为 ...

  8. 转:为什么说招到合适的人比融到钱更加重要 - Hiring Great Talent is More Important Than Fund Raising

    我在猎头行业工作了 20 多年,一直在帮助创业公司招聘优秀的人才.我服务过的客户既有 VC 投资的初创企业,也有即将 IPO 的公司.我和 200 多个 VC 合作过,也见过 300 多个客户失败的案 ...

  9. shell命令之at 执行一次性定时任务的用法

    大家都知道crontab是执行定时任务的命令,那么at又是什么呢? 其实at也是定时任务命令,不同的是crontab是执行循环任务,at执行一次性任务 首先说下时间例子 Minute    at no ...

  10. 遗传算法框架GAFT优化小记

    前言 前段时间一直在用自己写的遗传算法框架测试算法在优化力场参数的效果,但是跑起来效率很慢,因为适应度函数需要调用多次力场程序计算能量,但是还是比我预想中的慢我也没有及时对程序进行profiling和 ...