注意: 本文章为 《重学js之JavaScript高级程序设计》系列第三章第三部分【运算符】。

关于《重学js之JavaScript高级程序设计》是重新回顾js基础的学习。

1. 布尔操作符

布尔操作符的重要性堪比相等操作符。布尔操作符一个有3个,非(NOT)、与(AND)、或(OR)

1.1 逻辑非

逻辑非操作符由一个叹号(!)表示,可以应用于ES中的任何值。无论这个值是什么数据类型,这个操作符都会返回一个布尔值。逻辑非操作符首先会将它的操作数转换为一个布尔值,然后在对其求反,它遵循以下规则:

1. 操作数是一个对象,返回false
2. 操作数是一个空字符串,返回true
3. 操作数是一个非空字符串,返回false
4. 操作数是数值0,返回true
5. 操作数是任意非0数值,返回false
6. 操作数是null,返回true
7. 操作数是NaN,返回true
8. 操作数是undefined,返回true

注意:逻辑非也可以用于将一个值转化为与其对应的布尔值。而同时使用两个逻辑非操作符,实际上会模拟Boolean()转型函数的行为。其中,第一个逻辑非操作符会基于无论什么操作数返回一个布尔值,而第二个逻辑非操作则对该布尔值进行求反,于是就得到这个值真正对应的布尔值。

!!'blue'    // true
!!0     //  false
!!NaN   //  false
!!''    //  false
!!123   //  true

1.2 逻辑与

逻辑与操作符由两个和号(&&)表示,有两个操作数,只有两个操作符都为true的时候,结果才为true,其他都为 false 。如下:

操作数 1 操作数 2 结果
true true true
true false false
false true false
false false false

同样,逻辑与操作可以用于任何类型的操作数,而不仅仅是布尔值。在有一个操作不是布尔值的情况下,逻辑与操作就不一定返回布尔值,此时遵循如下规则:

1. 第一个操作数是对象,则返回第二个操作数
2. 第二个操作数是对象,则只有在第一个操作数
的求值结果为true的情况下才会返回该对象
3. 两个操作数都是对象,则返回第二个操作数
4. 有一个操作数是null,则返回null
5. 有一个操作数是NaN,  则返回NaN
6. 有一个操作数是undefined,则返回undefined

注意:逻辑与属于短路操作,即如果第一个操作数能够决定结果,那么就不会在对第二个操作数求值,对于逻辑与操作来说。如果第一个操作数是false,那么无论第二个操作数是什么值,结果也不可能是true了。另外重要的一点:不能在逻辑与操作中使用未定义的变量,会造成报错。

1.3 逻辑或

逻辑或操作符由两个竖线符号(||)表示,有两个操作数,与逻辑与相反,两个操作数只要有个为ture,结果就为true,如下:

操作数 1 操作数 2 结果
true true true
true false true
false true true
false false false

与逻辑与相似,如果有一个操作数不是布尔值,逻辑或也不一定返回布尔值,遵循如下下规则

1. 第一个操作数是对象,则返回第一个操作数
2. 第一个操作数的求值结果为false,则返回第二个操作数
3. 两个操作数都是对象,则返回第一个操作数
4. 两个操作数都是null,则返回null
5. 两个操作数都是NaN,则返回NaN
6. 两个操作数都是undefined,则返回undefined

注意:与逻辑与操作符相似,逻辑非操作符也是短路操作符,也就是说,如果第一个操作符的求值结果为 true,那么就不会在区对第二个操作数求值,结果就为 true。

2. 乘性操作符

ES 定义了3个乘性操作符:乘法、除法、求模。在操作符为非数值的情况下会自动执行类型转换。如果参与乘法计算的某个操作数不是数值,后台会使用 Number() 转型函数将其转换为数值,空字符会被当做 0,布尔值 true会被当做1.

2.1 乘法

乘法操作符(*)表示,用于计算两个数值的乘积。 如下:

var result = 43 * 22

注意:处理特殊值的情况下,乘法操作遵循以下规则:

1. 操作数都是数值,按照常规执行,如果两个正数或负数
结果还是正数,如果一正一负则是负数。如果值超过ES的表
示范围,则用 Infinity 或 - Infinity
2. 一个操作数为NaN,结果为NaN
3. Infinity 与 0 相乘,结果为NaN
4. Infinity 与 非0相乘,结果为Infinity 或 - Infinity
5. Infinity * Infinity,结果为Infinity
6. 如果有一个操作符不是数值,则调用Number()进行转换

2.2 除法

除法操作符由一个斜线符号(/)表示,执行第二个操作数除第一个操作数的计算。如下:

var result 44 / 33

注意: 和乘法类似,处理特殊值的情况如下:

1. 操作数都是数值,按照常规执行,如果两个正数或负数
结果还是正数,如果一正一负则是负数。如果值超过ES的表
示范围,则用 Infinity 或 - Infinity
2. 一个操作数为NaN,结果为NaN
3. 0 / 0 ,结果为NaN
4. Infinity 被任意值除,结果为Infinity
5. Infinity / Infinity,结果为 NaN
6. 如果有一个操作符不是数值,则调用Number()进行转换
7. 如果是 非0 的有限数被0除,结果是Infinity 或 - Infinity
8. 如果是 Infinity被任何 非0值除,结果是Infinity 或 - Infinity

2.3 求模

求模(余数)操作符由一个百分号(%)表示,如下:

var result = 33 % 2

注意:规则如下:

1. 操作数都是数值,执行常规的除法计算,返回除的余数
2. 被除数无穷大值,结果NaN
3. 被除数是有限大的数值而除数是0,则结果是NaN
4. Infinity 被 Infinity 除,结果NaN
5. 被除数是有限大的数值而除数是无穷大的数值,结果是被除数
6. 被除数是0,结果0
7. 有一个操作数不是数值,则调用Number()转换。

3. 加性操作符

加法和减法是最简单的算术操作符。

3.1 加法

var result = 1 + 2

注意:规则如下:

1. 有一个操作数是NaN,结果为 NaN
2. Infinity + Infinity, 结果是 Infinity
3. -Infinity + -Infinity, 结果 -Infinity
4. Infinity + -Infinity, 结果为 NaN
5. 0 + 0 = 0
6. -0 + -0 = -0
7.+0 + -0 = +0
8. 如果是两个字符串,则将字符串进行拼接
9. 如果两个有个不是字符串,则将非字符串转换成字符串在拼接。

3.2 减法

var result = 1 - 2

注意:规则如下:

1. 有一个操作数是NaN,结果为 NaN
2. Infinity - Infinity, 结果是 NaN
3. -Infinity - -Infinity, 结果 NaN
4. Infinity - -Infinity, 结果为 Infinity
5. -Infinity - Infinity, 结果为 -Infinity
6. 0 - 0 = 0
7. -0 - -0 = +0
8. +0 - -0 = -0
9. 如果有一个操作数是字符串、布尔值等则调用number()
进行转换为数值,在操作。
10. 如果一个操作数是对象,则调用valueOf()取得该对象
的值,在计算。如果没有valueOf()方法则调用toString()在计算。

4. 关系操作符

小于(<),大于(>),小于等于(<=),大于等于(>=)这几个关系操作符用于对两个值进行比较,比较规则和数学上一样。都返回布尔值。如果使用非数值,会进行数值转换,规则如下:

1. 两个操作数都是数值,则执行数值比较
2. 两个操作数都是字符串, 则比较两个字符串对应的字符编码
3. 一个操作数是数值,则将另外一个操作数转换为数值,在比较
4. 一个操作数是对象,则调用这个对象的valueOf()方法,在执行
之前的操作,如果没有这个方法在调用toString()方法。
5. 如果一个操作数是布尔值,则先将其转换为数值,在执行比较

注意:在比较两个字符串的时候,不是比较字符串中字母在字母表的位置,而是比较当前字母的ASCII码的大小。

5. 相等操作符

确定两个变量是否相等的关键操作。如果涉及到对象的比较,则先将对象转换成相似的类型。有两种方案 一 相等和不相等,先转换在比较,全等和不全等,仅比较不转换。

5.1 相等和不相等

由符号 (==)表示,如果两个操作数相等,则返回true,不等由符号(!=)表示,不相等的时候返回 true。这两个操作符都回转转换操作数在比较。是强制转换。规则如下:

1. 一个操作数是布尔值,比较之前先将其转换
成数值,false为0,true为1
2. 一个操作数是字符串,另一个不是,则调用
对象的valueOf()方法,在进行比较
3. 一个操作数是字符串,另一个操作数是数值,
则将字符串转换为数值在比较
4. null == undefined
5. 比较之前不能将null和undefined转换成其他值。
6. 一个操作数是NaN,则相等返回false,不相等
返回true。如果两个操作数都是NaN, 也是返回false,
因为 NaN != NaN
7. 两个操作数都是对象,则比较是不是同一个对象,
如果是则返回true否则false
表达式 表达式
null == undefined true true == 1 true
‘NaN’ == NaN false true == 2 false
5 == NaN false undefined == 0 false
NaN == NaN false null == 0 false
NaN != NaN false ‘5’ == 5 true
false == 0 true

5.2 全等和不全等

和相等不相等的区别就是比较之前不转换操作数,符号(===)它只有在两个操作数未经转换就相等的情况下返回 true,而(!==)不等于则是两个操作数在未经转换就不相等的情况下返回ture

// 全等
var result1 = ('55' == 55)  // true
var result2 = ('55' === 55) // false

// 不全等
var result1 = ('55 != 55)  // false
var result2 = ('55' !== 55) // true

建议:由于相等和不相等操作符存在类型转换问题,所以为了保证代码数据类型的完整,推荐使用全等和不全等。

6. 条件操作符

a = b ? c : d

// 如果b的值是true 那么 a = c 否则 a = d

7. 赋值操作符

简单的赋值操作符就是由(=)表示,作用就是把右侧的值赋给左侧的变量

var a = 10

// 如果在 = 的前面加上其他操作符就变成复合赋值操作

var a = 10
a = a + 10 === a += 10

// 复合赋值

(*=)乘
(/=)除
(%=)取模
(+=)加
(-=)减
(<<=)左移赋值
(>>=)有符号右移赋值
(>>>=)无符号右移赋值

8. 逗号操作符

var num = 1, a = 2, c =3;

9. 语句

语句就是使用一或多个关键字来完成给定任务。

9.1 if 语句

给定执行条件,如果条件符合则执行 if 内的代码块,否则执行 else 中的代码块。

var i = 10
if (i > 9) {
    // i > 9 执行这里
} else {
    // 否则执行这里
}

9.2 do-while 语句

一种后测试循环语句,即只有在循环体中的代码执行后,才会测试出口条件,也就是说条件表达式求值之前循环体的代码至少会被执行一次。

var i = 0;
do{
    i += 2
} while(i < 10)

9.3 while 语句

属于前测试循环语句,循环内的代码被执行之前,就会对出口条件求值。因此循环体的代码可能永远不会被执行;

var i = 0;
while (i < 10) {
    i += 2
}

9.4 for语句

也是一种前测试循环语句,但它具有在执行循环之前初始化变量和定义循环后要执行代码的能力。

var count = 10
for (var i = 0; i< count; i++) {
    alert(i)
}

9.5 for-in 语句

是一种精准的迭代语句,可以用来枚举对象的属性,如下:

for (var a in b) {
    alert(a)
}

// 因为ES对象的属性没有顺序,所以通过
for-in输出的属性名顺序也是不可预测的

9.6 label语句

使用label语句可以在代码中添加标签

label : a

s: for (var i = 0; i < c; i++) {
    alert(i)
}

9.7 break 和 countinue

用于程序在循环中精确地控制代码执行,break会立即推出循环,强制执行循环后面的语句,而countinue虽然也是立即退出循环,但是会从循环的顶部继续执行。

9.8 with语句

将代码的作用域设置到一个特定的对象中,大量使用with语句会导致性能下降,导致调试困难。

var b = a.c
var d = a.d
var u = a.t

with(a){
    var b = c
    var d = d
    var u = t
}

9.9 switch语句

流式控制语句,避免写过多的if else 判断。

var i = 2
switch (i) {
    case 2:
        alert(i)
        break;
}

10. 函数

通过函数可以封装任意多条语句,而且可以任何地方调用执行。 通过 function来声明,后面跟一组参数以及函数体

function a (b,c){
    alert(b + c)
}

a(2,4)

注意: 函数要么始终都返回一个值,要么始终都不返回。

11. 参数

ES中函数不介意传递多少个参数,也不在意参数的类型。因为在ES的参数在内部是用一个数组来表示,它不会关心这个数组包含什么参数。这个数组也可以为空。在函数体内可以通过 arguments对象来访问这个参数数组。从而获得传递给函数的每一个参数。

ES 中 所有的参数传递的都是值,不可能通过引用传递参数。

12. 没有重载

ES 函数不能像传统意义上那样实现重载,因为ES函数没用签名,其餐宿是由包含零或多个值的数组来表示的,没用函数签名,则真正的重载是不可能做到的。

13. 小结

  1. ES的基本数据类型包括 Undefined 、 Null 、Boolean、Number、String
  2. ES中没用为整数和浮点数分别定义不同的数据类型,Number类型可用于表示所有数值。
  3. ES也有复杂的数据类型,Object类型,该类型是所有对象的基础类型。
  4. ES提供了 算术操作符、布尔操作符、关系操作符、相等操作符、赋值操作符等
  5. ES提供了流控制语句,如 if语句 for语句 switch语句等。
  6. 无须指定函数的返回值,因为任何ES函数都可以在任何时候返回任何返回值
  7. 未指定返回值的函数返回的是一个特殊的undefined值,ES中没用函数签名的概念,因为函数参数是以一个包含零或多个值的数组的形式传递的。
  8. 可以向函数传递任意数量的参数,并且可以通过 argument 对象来访问这些参数
  9. 函数不能重载

欢迎关注 公众号【小夭同学】