任何编程语言基本上都离不开运算符。在 JavaScript 中也是支持众多运算符的。例如最常见的算数运算符,比较运算符,逻辑运算符等。接下来,就让我们一起来看一下 JavaScript 中这几种常见的运算符。
2-4-1 算数运算符
常见的算数运算符有加减乘除和取模运算。主要需要注意的就是,在动态语言中做除法运算时,能够得到小数。下面是关于算数运算符的示例:
console.log(5 + 3.14); // 8.14
console.log(6 - 11); // -5
console.log(7 * 3); // 21
console.log(5 / 2); // 2.5
console.log(10 % 3); // 1
从 ECMAScript 6 开始新增加了求幂运算,使用两个*
号代表求幂。以此可以代替以前的Math.pow()
方法
console.log(2 ** 3); // 8
2-4-2 一元运算符
所谓一元运算符,就是指只作用于一个操作数的运算符。常见的一元运算符有两种,赋值运算符和递增递减运算符。
1. 赋值运算符
关于赋值运算符,前面我们已经见到过了。最常见的就是=
,代表将右边的内容赋值给左边。除此之外,还有+=
、-=
、*=
等一系列赋值运算符,具体的示例如下:
let a = 5;
a += 5;
console.log(a); // 10
a -= 3;
console.log(a); // 7
a *= 5;
console.log(a); // 35
a /= 5;
console.log(a); // 7
a %= 2;
console.log(a); // 1
2. 递增和递减
除了上面所介绍的赋值运算符以外,常见的一元运算符还有递增和递减。在递增递减中,主要需要注意前置和后置的区别。如果是前置,那么是先自增或自减,然后参与运算。如果是后置,则是先参与运算,然后再自增或者自减,示例如下:
前置示例:
let a = 2;
let b = 10;
let c = --a + b;
let d = a + b;
console.log(a,b,c,d); // 1 10 11 11
后置示例:
let a = 2;
let b = 10;
let c = a-- + b;
let d = a + b;
console.log(a,b,c,d); // 1 10 12 11
需要注意的是,我们的自增自减操作符不仅仅局限于数值,其他类型也可以,遵循下面的规则:
- 在应用于一个包含有效数字字符的字符串时,现将其转换为数字值,再执行加减 1 操作。字符串变量变为了数值变量。
- 在应用于一个不包含有效数字字符的字符串时,将变量的值设置为 NaN,字符串变量变成数值变量。
- 遇布尔值 false 时,先将其转换为 0 再执行加减 1 操作,布尔值变量变成数值变量。
- 遇布尔值 true 时,先将其转换为 1 再执行加减 1 操作,布尔值变量变成数值变量。
- 在应用浮点数数值时,执行加减 1 操作。
示例:
let s1 = "123";
let s2 = "123Hello";
let s3 = "Hello";
let s4 = true;
let s5 = 3.14;
console.log(--s1); // 122
console.log(--s2); // NaN
console.log(--s3); // NaN
console.log(--s4); // 0
console.log(--s5); // 2.14
2-4-3 比较运算符
1. 关系运算符
常见的关系运算符有小于
,大于
,小于等于
,大于等于
,关于数的比较就不用说了,如下:
console.log(5 > 3); // true
console.log(3 > 5); // false
主要说一下字符串的比较,如下:
console.log("c" > "b"); // true
console.log("c" > "box"); // true
这里的比较主要是按照 ASCII 码来进行比较的。
如果是字符串和数字进行比较,那么会将字符串先转换为数字,如果不能转换为数字,则转换为 NaN
console.log("5" > 3); // true,因为"5"转为了5
// 任何一个数与 NaN 进行关系比较,返回的都是 false
console.log("Hello" > 3); // false,因为"Hello"转为了NaN
完整的特殊规则如下:
- 如果两个数都是数值,则执行数值比较
- 如果两个数都是字符串,则比较两个字符串对应的字符编码
- 如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值的比较
- 如果一个操作数是对象,则调用这个对象的
valueOf()
方法,用得到的结果按照前面的规则执行比较。如果对象没有valueOf()
方法,则调用toString()
方法,并用得到的结果根据前面的规则执行比较。 - 如果一个数是布尔值,则先将其转换为数值,然后再进行比较
还需要注意,任何数和 NaN 进行比较返回的都是 false
console.log(10 > NaN); // false
console.log(10 < NaN); // false
2. 相等和不相等
==
表示相等,!=
表示不相等,数据类型不同的数据进行相等比较的话会自动转换数据类型,还有一些其他的转换规则如下:
- null 和 undefined 是相等的
- 如果有一个操作数是 NaN,则返回 false,NaN 和 NaN 比较也是 false
- 如果是数字的字符串和数字进行比较,会先将字符串转换为数字
- 布尔值里面 true 转换为 1,false 转换为 0
下表列出了一些特殊的情况
表达式 | 值 |
---|---|
null == undefined | true |
"NaN" == NaN | false |
5 == NaN | false |
NaN == NaN | false |
NaN != NaN | true |
false == 0 | true |
true == 1 | true |
true == 2 | false |
undefined == 0 | false |
null == 0 | false |
"5" == 5 | true |
3. 全等和不全等
全等是===
,不全等是!==
,所谓全等,就是要求数据类型和数值都必须相等,如下:
console.log("5" == 5); // true
console.log("5" === 5); // false
2-4-4 逻辑运算符
1. 非
所谓非,就是取反,非真即假,非假即真
let i = true;
console.log(!i); // false
非运算符不仅仅只能用于布尔值,其他数据类型也是可以的,如下:
- 如果操作数是一个对象,返回 false
- 如果操作数是一个空字符串,返回 true
- 如果操作数是一个非空字符串,返回 false
- 如果操作数是数值 0,返回true
- 如果操作数是任意非 0 数值(包括 Infinity),返回 false
- 如果操作数是 null,返回 true
- 如果操作数是 NaN,返回 true
- 如果操作数是 undefined,返回 true
console.log(!false); // true
console.log(!"blue"); // false
console.log(!0); // true
console.log(!NaN); // true
console.log(!""); // true
console.log(!12); // false
可使用双否定!!
来判定一个值是真值还是假值,如下:
console.log(!!''); // false
console.log(!!NaN); // false
console.log(!!'Hello'); // true
2. 与
作用于两到多个值,并且只有所有的操作数都是真值时,才为 true
console.log(false && true); // false
console.log(true && true); // true
JavaScript里面的&&
存在短路现象,具体说明如下:
- 第一个操作数为真:会进入第二个操作数的判断,且无论第二个操作数真假,都会返回第二个操作数。
- 第一个操作数为假:不会进入第二个操作数的判断,直接返回第一个操作数。
来看下面的例子:
console.log(3 && 5); // 5
console.log("Hello" && 20); // 20
console.log("Hello" && false); // false
console.log("" && "shoe"); // ""
console.log("Hello" && ''); // ''
下面是关于&&
运算符的一道经典练习题:
let a = true;
let b = a && c; // 因为a是true,所以会判断第2个数
console.log(b);
// ReferenceError: c is not defined
let a = false;
let b = a && c; // 因为a是false,所以不会判断第2个数
console.log(b); // false
如果你看《JavaScript高级程序设计》这本书,里面还讲了诸如下面这些杂七杂八的规则:
- 如果第一个操作数是对象,则返回第二个操作数
- 如果第二个操作数是对象,则只有在第一个操作数的求值结果为 true 的情况下才会返回该对象
- 如果两个操作数都是对象,则返回第二个操作数
- 如果有一个操作数是 null,则返回 null
- 如果有一个操作数是 NaN,则返回 NaN
- 如果有一个操作数是 undefined,则返回 undefined
console.log(3 && 5); // 5
console.log(NaN && NaN); // NaN
console.log(null && null); // null
console.log(undefined && undefined); // undefined
但是这些规则大多都是可以使用短路现象来解释的,所以不需要你去记,大致了解即可。
3. 或
同样是作用于两到多个值,但是只要有一个操作数为真,就返回真
console.log(false || true); // true
console.log(true || false); // true
JavaScript 里面的||
同样存在短路现象,具体说明如下:
- 如果第一个操作数为真,则不会进入第二个数的判断。所以无论第二个操作数真假,都直接返回第一个操作数
- 如果第一个操作数为假,则会进入第二个数的判断。但是无论第二个操作数真假,都直接返回第二个操作数
来看下面的例子:
console.log(false || true); // true
console.log("Hello" || ""); // Hello
console.log("Hello" || "str"); // Hello
console.log(NaN || ""); // ""
console.log(0 || "Hello World"); // Hello World
console.log('' || 'str'); // str
console.log('' || false); // false
下面是关于||
运算符的一道经典练习题:
let a = false;
let b = a || c; // 因为a是false,所以会判断第2个数
console.log(b);
// ReferenceError: c is not defined
let a = true;
let b = a || c; // 因为a是false,所以会判断第2个数
console.log(b); // true
如果你看《JavaScript高级程序设计》这本书,里面也讲了诸如下面这些杂七杂八的规则:
- 如果第一个操作数是对象,则返回第一个操作数
- 如果第一个操作数的求值结果为 false,则返回第二个操作数
- 如果两个操作数都是对象,则返回第一个操作数
- 如果两个数都是 null,则返回 null
- 如果两个数都是 NaN,则返回 NaN
- 如果两个数都是 undefined,则返回 undefined
console.log(3 || 5); // 3
console.log(NaN || NaN); // NaN
console.log(null || null); // null
console.log(undefined || undefined); // undefined
不过这些规则大多也都是可以使用短路现象来解释的,所以根本不需要你去记,大致了解即可。
2-4-5 位运算符(扩展)
按位运算符是将操作数换算成32位的二进制整数,然后按每一位来进行运输。例如:
5 的32位为:
00000000000000000000000000000101
100 的32位为:
00000000000000000000000001100100
15 的32位为:
00000000000000000000000000001111
1. 按位非
按位非运算符~
会把数字转为32位二进制整数,然后反转每一位。所有的 1 变为 0,所有的 0 变为 1
例如:
5 的 32 位为:
00000000000000000000000000000101
~5 的 32 位为:
11111111111111111111111111111010
转换出来就为 -6
按位非,实质上是对操作数求负,然后减去1。
2. 按位与
按位或运算符&
会把两个数字转为 32 位二进制整数,并对两个数的每一位执行按位与运算。按位与的规则如下表:
第一个数字 | 第二个数字 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
具体示例:
console.log(12 & 10); // 8
12 的 32 位二进制表示为:1100
10 的 32 位二进制表示为:1010
按位与的结果为:1000
3. 按位或
按位或运算符|
会把两个数字转为 32 位二进制整数,并对两个数的每一位执行按位或运算。按位或的规则如下表:
第一个数字 | 第二个数字 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
具体示例:
console.log(12 | 10); // 14
12 的 32 位二进制表示为:1100
10 的 32 位二进制表示为:1010
按位或的结果为:1110
4. 按位异或
按位或运算符^
会把两个数字转为 32 位二进制整数,并对两个数的每一位执行按位异或运算。运算规则为两位不同返回 1,两位相同返回 0,如下表:
第一个数字 | 第二个数字 | 结果 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
具体示例:
console.log(12 ^ 10); // 6
12 的 32 位二进制表示为:1100
10 的 32 位二进制表示为:1010
按位异或的结果为:0110
按位异或如果是非整数值,如果两个操作数中只有一个为真,就返回 1,如果两个操作数都是真,或者都是假,就返回 0,示例如下:
console.log(true ^ "Hello"); // 1
console.log(false ^ "Hello"); // 0
console.log(true ^ true); // 0
console.log("Hello" ^ "Hello"); // 0
console.log(false ^ false); // 0
console.log(true ^ false); // 1
注意这里的 Hello 被转换为了 NaN
5. 按位移位
按位移位运算符<<
和>>
会将所有位向左或者向右移动指定的数量,实际上就是高效率地将数字乘以或者除以 2 的指定数的次方。
<<
:乘以 2 的指定数次方
console.log(2<<2); // 8
2 乘以 2 的 2 次方
00000010 转换为 00001000
>>
:除以 2 的指定数次方
console.log(16>>1); // 8
16 除以 2 的 1 次方
00010000转换为00001000
2-4-6 运算符优先级
JavaScript 中的运算符优先级是一套规则。该规则在计算表达式时控制运算符执行的顺序。具有较高优先级的运算符先于较低优先级的运算符执行。例如,乘法的执行先于加法。
下表按照最高到最低的优先级列出了 JavaScript 运算符。具有相同优先级的运算符按从左至右的顺序求值。
运算符 | 描述 |
---|---|
. [] () |
字段访问,数组下标,函数调用以及表达式分组 |
++ -- - ~ ! delete new typeof void |
一元运算符,返回类型,对象创建,未定义值 |
* / % |
乘法,除法,取模 |
+ - + |
加法,减法,字符串拼接 |
<< >> >>> |
移位 |
< <= > >= instanceof |
小于,小于等于,大于,大于等于,instanceof |
== != === !== |
等于,不等于,全等,不全等 |
& |
按位与 |
^ |
按位异或 |
| |
按位或 |
&& |
逻辑与 |
|| |
逻辑或 |
?: |
三目运算符 |
= |
赋值 |
, |
多重赋值 |
总结
拥有良好注释的代码是专业程序员的标志。如果没有注释,往往在几周后自己也很难明白自己写的代码的含义。
在 JavaScript 中,每一条代码以分号结束。
标识符就是我们自己给变量。函数或者对象起的一个名字。定义标识符时需要遵循一定的硬性要求和软性要求。
常见的命名法则有匈牙利命名法,驼峰命名法和蛇形命名法。
在 JavaScript 中存在一组关键字和保留字,不能用作自定义标识符。
在 JavaScript 中数据类型整体上可以分为简单数据类型和复杂数据类型。
使用 typeof 运算符可以查看一个数据的数据类型。
在 JavaScript 中声明变量可以使用 let,const 和 var 关键字来进行声明。
简单值和复杂值在访问方式,比较方式以及内存中存储空间的区别。
使用 var 关键字声明变量存在一些特殊的特性,例如重复声明以及遗漏声明
所谓作用域就是指变量在程序中能够被访问到的区域。常见的有全局作用域和局部作用域。
JavaScript 中存在 6 种基本数据类型,分别为 undefined,null,boolean,number,string和 symbol。
每种数据类型都有其对应的属性和方法。掌握这些属性和方法可以让我们在编写代码时事半功倍。
不同的数据类型之间可以相互进行转换,其中分为隐性转换和强制转换
JavaScript 中有众多的运算符,例如最常用的算数运算符,还有比较运算符,逻辑运算符,和位运算符等。不同的运算符之间有一套优先级关系。
Comments