
2024-11-29 日报 Day20

今日的鸡汤
躲起来的星星也在努力发光,你也要加油。
今日学习内容
1、JS红皮书P60-65 第三章:语言基础
今日笔记
1、位操作符: ECMAScript
中的所有数值都以 IEEE 754 64 位格式存储,但位操作并不直接应用到 64 位表示,而是先把值转换为32 位整数,再进行位操作,之后再把结果转换为 64 位。对开发者而言,就好像只有 32 位整数一样,因为 64 位整数存储格式是不可见的。既然知道了这些,就只需要考虑 32 位整数即可。
有符号整数使用 32 位的前 31 位表示整数值。第 32 位表示数值的符号,如 0 表示正,1 表示负。这一位称为符号位(sign bit),它的值决定了数值其余部分的格式。
负值是以补码形式存储的,即数值的绝对值的二进制形式取反后加 1。例如,-18 的二进制形式是 00000000 00000000 00000000 00010010,取反后是 11111111 11111111 11111111 11101101,加 1 后是 11111111 11111111 11111111 11101110。
2、按位非~
1 | let num1 = 25; // 二进制 00000000000000000000000000011001 |
这里,按位非操作符作用到了数值 25,得到的结果是26。由此可以看出,按位非的最终效果是对
数值取反并减 1,就像执行如下操作的结果一样:
1 | let num1 = 25; |
3、按位与&、按位或|、按位异或^、左移<<、有符号右移>>、无符号右移>>>。有符号右移由两个大于号(>>)表示,会将数值的所有 32 位都向右移,同时保留符号(正或负)。无符号右移由三个大于号(>>>)表示,会将数值的所有 32 位都向右移,同时用 0 填充最高位。
4、布尔操作符:逻辑非!、逻辑与&&、逻辑或||。
逻辑非操作符会遵循如下规则。
如果操作数是对象,则返回 false。
如果操作数是空字符串,则返回 true。
如果操作数是非空字符串,则返回 false。
如果操作数是数值 0,则返回 true。
如果操作数是非 0 数值(包括 Infinity),则返回 false。
如果操作数是 null,则返回 true。
如果操作数是 NaN,则返回 true。
如果操作数是 undefined,则返回 true。
以下示例验证了上述行为:
1 | console.log(!false); // true |
逻辑非操作符也可以用于把任意值转换为布尔值。同时使用两个叹号(!!),相当于调用了转型函数 Boolean()。无论操作数是什么类型,第一个叹号总会返回布尔值。第二个叹号对该布尔值取反,从而给出变量真正对应的布尔值。结果与对同一个值使用 Boolean()函数是一样的:
1 | console.log(!!"blue"); // true |
逻辑与操作符由两个和号(&&)表示,应用到两个值,如下所示:
let result = true && false;
逻辑与操作符可用于任何类型的操作数,不限于布尔值。如果有操作数不是布尔值,则逻辑与并不
一定会返回布尔值,而是遵循如下规则。
如果第一个操作数是对象,则返回第二个操作数。
如果第二个操作数是对象,则只有第一个操作数求值为 true 才会返回该对象。
如果两个操作数都是对象,则返回第二个操作数。
如果有一个操作数是 null,则返回 null。
如果有一个操作数是 NaN,则返回 NaN。
如果有一个操作数是 undefined,则返回 undefined。
逻辑与操作符是一种短路操作符,意思就是如果第一个操作数决定了结果,那么永远不会对第二个
操作数求值。对逻辑与操作符来说,如果第一个操作数是 false,那么无论第二个操作数是什么值,结
果也不可能等于 true。看下面的例子:
let found = true;
let result = (found && someUndeclaredVariable); // 这里会出错
console.log(result); // 不会执行这一行
上面的代码之所以会出错,是因为 someUndeclaredVariable 没有事先声明,所以当逻辑与操作符对它求值时就会报错。变量 found 的值是 true,逻辑与操作符会继续求值变量 someUndeclaredVariable。
但是由于 someUndeclaredVariable 没有定义,不能对它应用逻辑与操作符,因此就报错了。假如变量 found 的值是 false,那么就不会报错了:
let found = false;
let result = (found && someUndeclaredVariable); // 不会出错
console.log(result); // 会执行这里,console.log 会成功执行。即使变量 someUndeclaredVariable 没有定义,由于第一个操作数是 false,逻辑与操作符也不会对它求值,因为此时对&&右边的操作数求值是没有意义的。在使用逻辑与操作符时,一定别忘了它的这个短路的特性。
逻辑或操作符由两个竖线(||)表示,应用到两个值,如下所示:
let result = true || false;
与逻辑与类似,如果有一个操作数不是布尔值,那么逻辑或操作符也不一定返回布尔值。它遵循如下规则。
如果第一个操作数是对象,则返回第一个操作数。
如果第一个操作数求值为 false,则返回第二个操作数。
如果两个操作数都是对象,则返回第一个操作数。
如果两个操作数都是 null,则返回 null。
如果两个操作数都是 NaN,则返回 NaN。
如果两个操作数都是 undefined,则返回 undefined。
同样与逻辑与类似,逻辑或操作符也具有短路的特性。只不过对逻辑或而言,第一个操作数求值为true,第二个操作数就不会再被求值了。看下面的例子:
let found = true;
let result = (found || someUndeclaredVariable); // 不会出错
console.log(result); // 会执行
跟前面的例子一样,变量 someUndeclaredVariable 也没有定义。但是,因为变量 found 的值为 true,所以逻辑或操作符不会对变量 someUndeclaredVariable 求值,而直接返回 true。假如把
found 的值改为 false,那就会报错了:
let found = false;
let result = (found || someUndeclaredVariable); // 这里会出错
console.log(result); // 不会执行这一行
利用这个行为,可以避免给变量赋值 null 或 undefined。比如:
let myObject = preferredObject || backupObject;