02 【JS表达式与操作符】
什么是表达式和运算符?
表达式:由 操作数 和 运算符 组成的式子。
表达式的分类:算术、关系、逻辑、赋值、综合。
1.算术表达式
Section titled “1.算术表达式”1.1 算术运算符
Section titled “1.1 算术运算符”| 意义 | 运算符 |
|---|---|
| 加 | + |
| 减 | - |
| 乘 | * |
| 除 | / |
| 取余 | % |
推荐一律使用
()来强制规定优先级!
+ 有 “加法” 和 “连字符” 两种作用,如果 + 的某一边是字符串那么就为 ”连字符“,否则为 ”加法“。
1.2 隐式类型转换
Section titled “1.2 隐式类型转换”如果参与数学运算的某操作数不是数字类型,那么 JS 会自动将此操作数转换为数字型。
隐式转换的本质是 JS 内部自动调用 Number() 函数
1.3 有关IEEE754
Section titled “1.3 有关IEEE754”在 JS 中,有些小数的数学运算不是很精准。
JS 使用了 IEEE754 二进制浮点数算术标准,这会使一些个别的小数运算产生 “丢失精度” 问题。
注意:不是所有的小数运算都会出现精度问题,只是少数部分。
几乎所有的高级语言都使用了 IEEE754 二进制浮点数算术标准。
IEEE754 二进制浮点数算术标准是计算机底层编译标准,了解即可!
【解决办法】
在进行小数运算时,要调用数字的 toFixed() 方法保留指定的小数位数。
toFixed()括号内接受一个保留小数位数的参数。
toFixed()遵循 “四舍五入” 原则。
最后要注意浮点数的相等比较:
这不是 JavaScript 的设计缺陷。浮点数在运算过程中会产生误差,因为计算机无法精确表示无限循环小数。要比较两个浮点数是否相等,只能计算它们之差的绝对值,看是否小于某个阈值:
还有一种解决技巧,就是将浮点数转换为整数进行计算:
1.4 幂和开根号
Section titled “1.4 幂和开根号”JS 中没有提供幂运算、开根号的运算符,需要使用 Math 对象的相关方法进行计算。
Math.pow(a, b):求 a 的 b 次方。
Math.sqrt(a):求 a 的平方根。
1.5 向上取整和向下取整
Section titled “1.5 向上取整和向下取整”Math.ceil():向上取整。
Math.floor():向下取整。
Math.round():把一个数字舍入为最接近的整数(“四舍六入”,“五不一定”)
注意:向上、向下的标准是:X轴正方向为上!
负 ———— 0 ————> 正
2.1 关系运算符
Section titled “2.1 关系运算符”| 意义 | 运算符 |
|---|---|
| 大于 | > |
| 小于 | < |
| 大于或等于 | >= |
| 小于或等于 | <= |
| 等于 | == |
| 不等于 | != |
| 全等于 | === |
| 不全等于 | !== |
2.2 相等和全等
Section titled “2.2 相等和全等”两个等号 == 运算符,不考虑值的类型,它会进行隐式转换后比较值的字面量是否相等。
三个等号 === 运算符,不仅比较值是否相同,也比较类型是否相同。
null 和 undefined 用 == 进行比较涉及隐式强制类型转换,ES5 规范中规定。
=== 比较为 false,是因为 null 与 undefined 类型不同。
建议没有特殊情况请一律使用 ===
2.3 NaN不自等
Section titled “2.3 NaN不自等”NaN 作为一个特殊的数字类型值,它在用 == 比较的时候也有特殊的结果。
【如何判断某变量值为 NaN】
isNaN() 函数可以用来判断变量值是否为 NaN。
但 isNaN() 也不好用,它的机理是:只要该变量传入 Number() 的执行结果是 NaN,则 isNaN() 函数都会得到 true。
对于,undefined 和 null,这种情况一般来说需要先进行单独判断,再进行 isNaN 判断。
2.4 JS中没有连比
Section titled “2.4 JS中没有连比”例如:3 <= a <= 15 的写法是错误的,应该为:a >= 3 && a <= 15。
3.逻辑表达式
Section titled “3.逻辑表达式”3.1 逻辑运算符
Section titled “3.1 逻辑运算符”| 意义 | 运算符 |
|---|---|
| 非 | ! |
| 与 | && |
| 或 | ` |
3.2 非运算
Section titled “3.2 非运算”! 表示 “非”,也可以称为 “置反运算”。
! 是一个 “单目运算符”,只需要一个操作数。
置反运算的结果一定是布尔值。
!!常用于确定一个值的布尔属性。
3.3 与运算
Section titled “3.3 与运算”&& 是 “双目运算符”。
核心:全真为真、有假即假。
3.4 或运算
Section titled “3.4 或运算”|| 是 “双目运算符”。
核心:全假为假、有真即真。
3.5 短路运算
Section titled “3.5 短路运算”&& 与 ||,都属于 “短路运算符”。
(1)&& 短路运算
由于 && 运算的核心是:“全真为真、有假即假”,所以:
- 如果
a && b中a为真,那么该表达式的值由b决定(计算 a 又计算 b) - 如果
a && b中a为假,那么该表达式的值由a决定(只计算 a)
(2)|| 短路运算
由于 || 运算的核心是:“全假为假、有真即真”,所以:
- 如果
a || b中a为真,那么该表达式的值由a决定(只计算 a) - 如果
a || b中a为假,那么该表达式的值由b决定(计算 a 又计算 b)
3.6 逻辑运算的优先级
Section titled “3.6 逻辑运算的优先级”优先级:! > && > ||
推荐使用
()来规定优先级。
4.赋值表达式
Section titled “4.赋值表达式”4.1 赋值运算符
Section titled “4.1 赋值运算符”| 意义 | 运算符 |
|---|---|
| 赋值 | = |
| 快捷赋值 | +=、-=、*=、/=、%= |
| 自增运算 | ++ |
| 自减运算 | -- |
4.2 赋值运算产生值
Section titled “4.2 赋值运算产生值”赋值运算也产生值,等号后面的值将作为 “赋值运算的值”。
这就意味着,可以连续使用赋值运算符。
在实际开发中不建议使用连续赋值!
4.3 自增自减运算
Section titled “4.3 自增自减运算”a++:先用再加;++a:先加再用。
自增可以使变量在原值的基础上自增1
自增使用 ++
自增可以使用 前++(++a)后++(a++)
无论是++a 还是 a++都会立即使原变量自增1
不同的是++a和a++的值是不同的,
++a的值是变量的新值(自增后的值)
a++的值是变量的原值(自增前的值)
a--:先用再减;--a:先减再用。
自减可以使变量在原值的基础上自减1
自减使用
自减可以使用 前(a)后(a)
无论是a 还是 a都会立即使原变量自减1
不同的是a和a的值是不同的,
a的值是变量的新值(自减后的值)
a的值是变量的原值(自减前的值)
5.三元运算符
Section titled “5.三元运算符”条件表达式 ? 表达式1 : 表达式2;
当条件表达式为真时执行表达式1并返回结果,否则执行表达式2并返回结果。
【三元运算符的用途】
根据某个条件是否成立,在两个不同值中选择变量的值。
6.综合运算的运算顺序
Section titled “6.综合运算的运算顺序”和数学中一样,JS中的运算符也是具有优先级的,
比如 先乘除 后加减 先与 后或
具体的优先级可以参考优先级的表格,在表格中越靠上的优先级越高,
优先级越高的越优先计算,优先级相同的,从左往右计算。
非运算 > 数学运算 > 关系运算 > 逻辑运算
优先级不需要记忆,如果越到拿不准的,使用()来改变优先级。