基本

+加
- 减

/ 除
% 取余
*
指数(ES7新增)

注意!js的除和java不一样,js是5/2=2.5,java是5/2=2
var y = 5 ** 2;//y=25

表达式

image.png

一元运算符(自增自减)

  1. ++1;
  2. --1;
  3. 1++;
  4. 1--;
  5. //1.x++、x--;
  6. //相当于先用x的值,再进行下一条语句x=x+1、或者x=x-1;
  7. //2.++x、--x;
  8. //相当于先运算x=x+1、或者x=x-1后,再用x的值;

其他

  1. let s1 = "2";
  2. let s2 = "z";
  3. let b = false;
  4. let f = 1.1;
  5. let o = {
  6. valueOf() {
  7. return -1;
  8. }
  9. };
  10. s1++; // 值变成数值 3
  11. s2++; // 值变成 NaN
  12. b++; // 值变成数值 1
  13. f--; // 值变成 0.10000000000000009(因为浮点数不精确)
  14. o--; // 值变成-2

位运算符

用于数值的底层操作,也就是操作内存中表示数据的比特(位)

ECMAScript中的所有数值都以 IEEE 754 64 位格式存储,但位操作并不直接应用到 64 位表示,而是先把值转换为32 位整数,再进行位操作,之后再把结果转换为 64 位。

对开发者而言,就好像只有 32 位整数一样.

有符号整数使用 32 位的前 31 位表示整数值。第 32 位表示数值的符号,如 0 表示正,1 表示负

image.png

在对 ECMAScript 中的数值应用位操作符时,后台会发生转换:64 位数值会转换为 32 位数值,然后执行位操作,最后再把结果从 32 位转换为 64 位存储起来。

补码

负值以一种称为二补数(或补码)的二进制编码存储。

(1) 确定绝对值的二进制表示(如,对于-18,先确定 18 的二进制表示);
0000 0000 0000 0000 0000 0000 0001 0010

(2) 找到数值的一补数(或反码),换句话说,就是每个 0 都变成 1,每个 1 都变成 0;
1111 1111 1111 1111 1111 1111 1110 1101

(3) 给结果加 1。
1111 1111 1111 1111 1111 1111 1110 1101
1
———————————————————————
1111 1111 1111 1111 1111 1111 1110 1110

那么,-18 的二进制表示就是 11111111111111111111111111101110。要注意的是,在处理有符号整数时,我们无法访问第 31 位。

按位非 ~

对数值取反并减 1

  1. let num1 = 25; // 二进制 00000000000000000000000000011001
  2. let num2 = ~num1; // 二进制 11111111111111111111111111100110
  3. // 或
  4. let num2 = -num1 - 1; //尽管两者返回的结果一样,但位操作的速度快得多。这是因为位操作是在数值的底层表示上完成的。
  5. console.log(num2); // -26

按位与 &

本质上,按位与就是将两个数的每一个位对齐,两个位都是 1 时返回 1,在任何一位是 0 时返回 0。

  1. let result = 25 & 3;
  2. console.log(result); // 1

25 = 0000 0000 0000 0000 0000 0000 0001 1001
3 = 0000 0000 0000 0000 0000 0000 0000 0011
——————————————————————-
= 0000 0000 0000 0000 0000 0000 0000 0001

按位或 |

按位或操作在至少一位是 1 时返回 1,两位都是 0 时返回 0

按位异或 ^

在一位上是 1 的时候返回 1(两位都是 1 或 0,则返回 0)。

左移 <<

所有位向左移动

  1. 2 << 5; // 值 2(二进制 10)向左移 5 位,就会得到 64(二进制 1000000)

image.png

有符号右移 >>

  1. 64 >> 5; // 将 64 右移 5 位,那就是 2
  2. -64 >> 5; // 将 -64 右移 5 位,那就是 -2

image.png

无符号右移 >>>

正数操作时,和有符号右移一样。负数时差别很大

  1. let oldValue = -64; // 等于二进制 11111111111111111111111111000000
  2. let newValue = oldValue >>> 5; // 等于十进制 134217726

逻辑(重要)

普通逻辑

&& 与
如果有一个操作数是 null,则返回 null。
如果有一个操作数是 NaN,则返回 NaN。
如果有一个操作数是 undefined,则返回 undefined。
|| 或
! 非
//优先级:与>或>非

1、执行顺序

  1. console.log(1 && 2);
  2. // 输出为2,为什么是2?因为逻辑运算的结果,是决定整个表达式的子表达式的值。
  3. // 因为前面是1无法判断整个表达式是否结束,要判断后面的,因此得到的就是后面的值
  4. console.log(1 || 2);
  5. // 结果为1,因为判断左边那个就已经可以确定得到true了,因此不用去看右边的。
  6. var obj = {
  7. name:"YJL",
  8. run:function(){
  9. console.log("我会跑步");
  10. }
  11. }
  12. // 利用这个行为,可以避免给变量赋值 null 或 undefined。比如:
  13. let myObject = preferredObject || backupObject;
  14. var abb = obj.name || obj.run;
  15. // 下面的空值合并运算符 ?? 也是这样的效果
  16. // 下面的逻辑赋值也是这样的效果

2、执行函数不报错

  1. var obj = {
  2. name:"YJL",
  3. run:function(){
  4. console.log("我会跑步");
  5. }
  6. }
  7. obj.run && obj.run();
  8. //如果函数obj.run 存在的话,就会执行obj.run()。避免了函数不存在导致报错

逻辑赋值(ES12)

相当于逻辑比较后再赋值

或:左边有的情况下用左边的,没有就用右边的,赋值给左边
image.png

与:左边右边都存在的情况下,执行右边的,然后把返回值赋值给左边的,否则就什么都不做
image.png

比较

大于
< 小于
>= 大于等于
<= 小于等于
== 是否想等
=== 是否全相等
!= 不等

自动转换

  1. console.log("A" < "a"); //true,字符串相比,会逐个比较字母的字符的编码,编码小的就小
  2. let result = "B".toLowerCase() < "b".toLowerCase(); // false,可以全部提升或降低来比
  3. let result = "23" < "3"; // true

如果操作数都是数值,则执行数值比较。

如果操作数都是字符串,则逐个比较字符串中对应字符的编码(从左到右,比较1个,一般小写字母比大写的大)

  1. let result = "23" < "3"; // true

如果有任一操作数是数值,则将另一个操作数转换为数值,执行数值比较。

  1. let result = "a" < 3; // 因为"a"会转换为 NaN,所以结果是 false

如果有任一操作数是对象,则调用其 valueOf()方法,取得结果后再根据前面的规则执行比较。

如果没有 valueOf()操作符,则调用 toString()方法,取得结果后再根据前面的规则执行比较。

比较 NaN 时,无论是小于还是大于等于,比较的结果都会返回 false

尽量用===。
image.png

全等===

  1. console.log("2" == 2); //true,自动转换
  2. console.log("2" === 2); //false,连数据类型也判断是否相等

image.png

浮点数的相等比较

浮点数在运算过程中会产生误差,因为计算机无法精确表示无限循环小数。要比较两个浮点数是否相等,只能计算它们之差的绝对值,看是否小于某个阈值:

Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001; // true

转换成布尔 !!

  1. console.log(!!"blue"); // true
  2. console.log(!!0); // false
  3. console.log(!!NaN); // false
  4. console.log(!!""); // false
  5. console.log(!!12345); // true
  6. //相当于使用了Boolean()函数

=====================

其他 *

赋值运算 =

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

  1. var a =1;
  2. //赋值
  3. a += 1;
  4. //相当于a = a + 1;

好处就是不会改变变量的数据类型。

条件(三元运算符) ? : *

相当于if判断,简写

  1. //(判断条件) ? 执行语句1 : 执行语句2
  2. (2>1)?"是":"不是"

可选链操作符 ?. (ES11) *

正常,如果config没传就报错
image.png image.png
在开发中,很容易出现获取某个不存在的属性导致报错(比如服务器返回的数据对象),报错的信息是无法获取undefined的属性grilFriend。
image.png如果这样写,对象里面没有就会报错,报错的结果是后面逻辑全部都不会执行,严重的安全隐患。
为了解决这个问题,我们可能会先做判断,很麻烦,尤其是在Vue中给template中加v-if作判断
image.png

ES11 提供了可选链,如果后面没有,直接就直接返回undefined,不会报错
image.png

?.
判断前一个有没有,有才读取后面的,没有就返回undefined
image.png

逗号操作符 ,(ES6)

对它的每个操作数求值(从左到右),并返回最后一个操作数的值。

  1. let a = 1;
  2. let b = (a+=1, 11);
  3. // 相当于
  4. let a = 1;
  5. a+=1;
  6. let b = 11;

这个操作符最常用的一种情况是:for 循环中提供多个参数:

  1. for (var i = 0, j = 9; i <= 9; i++, j--)
  2. document.writeln("a[" + i + "][" + j + "] = " + a[i][j]);

我们偶尔会在一些框架的源码里面看到这样的写法(如下)

  1. var a = {
  2. foo: function() {
  3. console.log(this);
  4. }
  5. };
  6. a.foo(); // a
  7. (0, a.foo)(); // window
  8. // 相当于 a.foo.apply(window)

原因是最后返回的是最后一个参数的值,上面例子也就是function(){console.log(this)},然后在全局的情况下调用,也就是this指向window。

作用是可以安全地在全局的环境下执行,忽略执行的平台(浏览器的全局是window,而Node.JS的全局是{ })

数组 扩展运算符 … (ES6)

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_syntax
image.png

image.png
image.png 数组里面有引用的不行

image.pngimage.png
image.png

对象 扩展运算符 与 rest参数(ES9)

image.png
image.png
image.pngimage.png
image.png
image.png
image.png

空值合并 ?? (ES11)

类似于逻辑或,如果左边的是空值、空字符串、0等,会转换成布尔类型的数据(true、false),就会使用右边的
image.png“default value”
但是有个问题,如果我只想用空字符””,或者0,就没办法这样。

而空值合并运算符,更好地解决这个问题,如果左边是undefined或null,才用右边的
image.png 0

空值合并赋值(ES12)

image.png
和上面空值合并一样,相当于 foo = foo ?? “默认值”