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