犀牛书笔记(第4章)
数组初始化程序的最后一个表达式后面可以跟一个逗号,这个逗号不会创建未定义元素。通过数组访问表达式访问最后一个表达式后面的索引一定返回undefined.
基本表达式有如下几种:基本类型字面量、某些保留字如null/true/false、基本类型变量。
类似链式的对象或者数组访问表达式中可以用问号造成短路,函数调用也可以。a?.(), 如果a是null/undefined,则函数表达式返回undefined, 不报错。但是如果a不是函数,则检查不出来,还是会试图进行函数调用,结果就是报错。

条件调用是短路的:如果问号前面的表达式值为null/undefined, 直接返回,括号里类似参数++这样的操作不会真正执行。a.b为null, 那么a.b?.c.d是undefined, 但(a.b?.c).d会抛出TypeError异常。
对象创建表达式:即构造函数调用。如果没有参数,可以 不加括号。new Object;
关于操作符优先级:最重要的规则是乘除高于加减,赋值优先级很低。但是js新增的操作符并不总是符合这个优先级模式。比如??操作符相对于||和&&,优先级无定义,ES2020要求混用时必须使用括号。类似**(求幂)相对于-(求负值)也没有明确定义,混用时需要使用括号。
操作符的优先级和结合性规定了复杂表达式中操作的执行顺序,但它们没有规定子表达式的求值顺序。js按照严格的从左到右的顺序求值。求值顺序只在一种情况下有用,就是某表达式有负作用。
算数表达式:
执行算数或者其他数值操作的操作符。优先级幂>乘除模>加减。
Js中的数字都是浮点数,所以除法的结果如果除不尽,是小数。
%取余运算,结果的符号与被除数相同。
+号,对数字是加法,对字串是连接操作。如果操作数中有数字有字符串,则字符串优先级更高。运算法则:
如果有一个操作数是对象,则+操作符把操作数转为原始值(Date toString, 其他 valueOf)。如果没有valueOf, 也使用toString。 完成对象到原始值的转换后,如果有操作数是字符串,则另一个操作数也会转为字符串并拼接。如果没有字串,两个操作数都转为数值并计算加法。
算数一元操作符:+/-/++/–, 全部是高优先级和右结合性。必要时会把自己的操作数转为数字。一元加号:不能用于BigInt. ++和–后面都只能跟左值。

x++不一定等价于x = x + 1. ++操作符不会执行字符串拼接,而是始终会将其操作数转换为数值。如果x是字符串“1”, ++x就是数值2,但x+1是字符串“11”。
位操作符:期待32位整数,而非64位浮点数。如果硬塞给位操作符一个64位的浮点数,js会丢弃小数部分和32位之外的整数部分。

有符号右移:>> 最左边的位用符号位填充;0填充右移:>>> 左边位用0填充。0填充右移不适用于BigInt.
关系表达式:相等、不等、比较操作符、in、instanceof.
=== 严格相等号比较的逻辑:

== 基于类型转换的相等比较:


比较操作符:> , <, >=, <= 只能用于数字或者字符,其他类型要比较的话,需要先转成数字或者字符。
转换规则:


+和比较操作符都会对数值和str区别对待,但是+偏向字符串拼接,即 数字 + 字符串会按字符串拼接处理;而比较操作符偏重数值比较,即两个都是字符串才会按字符序比较。
in操作符的右侧操作数可以是数组。
instanceof在判断对象是否是某类实例的时候会考虑继承。即子类对象 instanceof 父类,为true。
逻辑表达式:
&&、||、!
&&的操作数可以是布尔值也可以不是,它也可以对Js里的“真性值”和“假性值”做判断。假值包括,false, null ,undefined, NaN, ” , 0, -1。 其他数据包括所有的对象都是真性值。
何如求表达式x的对应布尔值:!!x.
赋值表达式:
=,左边必须是左值,优先级低。赋值表达式求值为右边的操作数。
求值表达式:
eval: 不推荐使用。
直接调用eval,代码字符串执行使用的是调用上下文的变量环境,称为直接调用。把eval赋值给其他值,进行调用,使用全局对象作为调用上下文,不能读、写、定义 局部变量和函数。

先定义操作符:?? 。a ?? b等价于 (a !== null && a !== undefined) ? a : b。 这个操作符也是短路的,即如果返回a, 那么b就不计算了,副作用不起作用。
??的应用场景:是对||的有效补充。适合选择先定义的操作数,而非第一个不为假的操作数。即 maxWidth || 100, 如果0是有效的maxWidth值,那这时候使用||就不合适。
typeof操作符:

delete操作符删除数组中的元素,不会改变数组长度。
