今天的主角:

Operator Description
一元正值符 " + "(MDN) 一元运算符, 如果操作数在之前不是number,试图将其转换为number

圆括号运算符 " () "(MDN)

圆括号运算符由一对圆括号组成,包裹表达式和子表达式用来覆盖常规的运算符优先级(MDN),达到低优先级的表达式比高优先级的表达式更早运算。

一元正值符 - " + "

? 为什么图例 - 3中 +'1.22' + 1.5 = 2.71999999… ? 查看我的另一篇文章:深入探讨带浮点数运算丢失精度问题(二进制的浮点数存储方式)

首先区分如 let x = '1.20' 是作为变量声明被浏览器解析,包括 function / let / var / const / class 等等这些都是作为 声明语句 被解析。

浏览器预解析到声明语句,则会将其存入堆栈区并为其分配存储空间。

  运算符 - 一元正值符(+)  的作用是 声明语句 --> 表达式语句(“ 使某件事发生 ” 的计算带有副作用的表达式)。

它为什么带有副作用:

除了基本数据类型外,任何数据都会被正值运算符 “ + ” 转换成Number类型数据,包括ObjectArray的引用如

let me = {
name: '97z4moon',
age: '24.00'
} console.log(typeof +me.age, ': ', +me.age)
// number: 24
console.log(typeof +me.name, ': ', +me.name)
// number: NaN

若数据无法被转换成Number类型,则仍然返回number类型的NaN。除此之外,JS特别的 “ Date对象 ” 也是能够被转换成Number类型的数据:

window.onload = function(){
console.log(new Date())
// Wed Apr 07 2021 17:17:12 GMT+0800 (中国标准时间) console.log(new Date().getTime())
// 1617787032426
console.log(+new Date())
// 1617787032426
}

new Date( ) 在正值符作用下等同于 new Date( ).getTime( ) ,发现这一点的我甚至怀疑了 getTime( ) 的存在价值。

小总结

  • 声明语句(MDN):将一条数据、一个函数、一块语句等等声明成一个变量,在堆栈区为其分配内存空间,需要特别注意的是  声明提升(hoisting)
  • 表达式语句(MDN):“ 使某件事发生 ” 的计算带有副作用的语句,需要特别注意的是 运算符的副作用 
  • 运算符(MDN):对单 / 多个数据进行特定规则的运算,有些运算符会包含一些附加作用,如尝试对参与运算数据进行类型转换(Number)的一元正值符 “ + ” ,它们往往会对数据造成意料之外的效果,需要特别注意的是 运算符的优先级

圆括号运算符 - " ( ) "

分组运算符 - 使低优先级比高优先级更早运算。

  1 + 2   * 2     // 5
( 1 + 2 ) * 2 // 6

但我们知道" () " 在JS中还充当其他重要的作用,它们脱离了运算符的概念:

参数传递

funA(12)不是为了优先执行“ 12 ”,它起着另一种至关重要的作用。除此之外它还有其他的作用:

函数调用

funA()

限定作用

条件语句 (Condition)

if (i < 10) { // Some code. }

循环语句 (Loop)

for (var i = 0; i < 10; i++) { // Some code. }

强制表达式运算

我们都知道 ( 1 + 2 ) * 2 能够执行,那么 ( 1 + 2 ) 呢,( 2 ) 呢?

最常用的立即执行函数 Immediately-Invoked Function Expression (IIFE)由此诞生:

图例 -1 和 图例 -2 写法相似,结果相同,但它们绝不相同,浏览器内部发生的事情绝对刺激!

了解立即执行函数的原理,请阅读我的另一篇文章:JS016. 详解匿名函数_立即执行函数_递归函数(自执行函数)

运算符 - 优先级 & 结合性 & 分组短路

运算符有优先级,就如css的权值一样有不同的执行顺序,而一个表达式除了优先级,还有结合性。

我们大多数情况遇到的都是左结合(左到右),如:

2 + 3 * 4    // 2 + 12
1 * 2 ** 3 // 1 * 8

而有些个例是作为右结合被解析的,如赋值运算符:

a = b = 5
// 等价于
a = ( b = 5 )

另一个例子是,只有幂运算符是右结合的,而其他算术运算符都是左结合的。有趣的是,无论结合性和优先级如何,求值顺序总是从左到右

混合求除法和幂:

2 ** 3 / 3 ** 2    //0.8888888888888888...
//等价于
( 2 ** 3 ) / ( 3 ** 2 )

还有一个很常用且很有趣的意外情况:分组与短路

分组( Group )在下表中拥有最高优先级,但并不意味着浏览器总是对分组符号 (...) 内的表达式优先求值,比如涉及到短路时。

短路是条件求值的术语。例如,在表达式  a && ( b + c )  中,如果 a 为虚值(falsy),那么即使 ( b + c ) 在圆括号中,也不会被求值。我们可以说逻辑或运算符(" OR ")是 “短路的”。

除了逻辑或运算符外,其他短路运算符还包括逻辑与(" AND ")、空值合并、可选链和条件(三元)运算符。

a || (b * c);  // 首先对 `a` 求值,如果 `a` 为真值则直接返回 `a` (变量a储存的值)
a && (b < c); // 首先对 `a` 求值,如果 `a` 为虚值则直接返回 `a` (false)
a ?? (b || c); // 首先对 `a` 求值,如果 `a` 不是 `null` 或 `undefined` 则直接返回 `a`
a?.b.c; // 首先对 `a` 求值,如果 `a` 是 `null` 或 `undefined` 则直接返回 `undefined`

3 > 2 && 2 > 1
// 返回 true 3 > 2 > 1
// 返回 false,因为 3 > 2 是 true,然后 true 会在比较运算符中
// 被隐式转换为 1,因此 true > 1 会变为 1 > 1,结果是 false
// 加括号可以更清楚:(3 > 2) > 1

 汇总表

优先级 运算符类型 结合性 运算符
21 分组 n/a(不相关) ( … )
20 成员访问 从左到右 … . …
需计算的成员访问 从左到右 … [ … ]
new(带参数列表) n/a new … ( … )
函数调用 从左到右 … ( … )
可选链(Optional chaining) 从左到右 ?.
19 new(无参数列表) 从右到左 new …
18 后置递增 n/a … ++
后置递减 … --
17 逻辑非 (!) 从右到左 ! …
按位非 (~) ~ …
一元加法 (+) + …
一元减法 (-) - …
前置递增 ++ …
前置递减 -- …
typeof typeof …
void void …
delete delete …
await await …
16 幂 (**) 从右到左 … ** …
15 乘法 (*) 从左到右 … * …
除法 (/) … / …
取余 (%) … % …
14 加法 (+) 从左到右 … + …
减法 (-) … - …
13 按位左移 (<<) 从左到右 … << …
按位右移 (>>) … >> …
无符号右移 (>>>) … >>> …
12 小于 (<) 从左到右 … < …
小于等于 (<=) … <= …
大于 (>) … > …
大于等于 (>=) … >= …
in … in …
instanceof … instanceof …
11 相等 (==) 从左到右 … == …
不相等 (!=) … != …
一致/严格相等 (===) … === …
不一致/严格不相等 (!==) … !== …
10 按位与 (&) 从左到右 … & …
9 按位异或 (^) 从左到右 … ^ …
8 按位或 (|) 从左到右 … | …
7 逻辑与 (&&) 从左到右 … && …
6 逻辑或 (||) 从左到右 … || …
5 空值合并 (??) 从左到右 … ?? …
4 条件(三元)运算符 从右到左 … ? … : …
3 赋值 从右到左 … = …
… += …
… -= …
… **= …
… *= …
… /= …
… %= …
… <<= …
… >>= …
… >>>= …
… &= …
… ^= …
… |= …
… &&= …
… ||= …
… ??= …
2 yield 从右到左 yield …
yield* yield* …
1 逗号 / 序列 从左到右 … , …

- END -

最新文章

  1. Android Studio accelerator key(shortcut)&amp; Basic knowledge
  2. linux命令每日一练习 wc more
  3. js数组的队栈操作
  4. 原博客地址http://blog.chinaunix.net/uid/20656672.html弃用
  5. C语言字符串与数字相互转换
  6. hdfs创建级联文件夹
  7. 数据结构-AVL树
  8. [!!!!!]Inno Setup教程-常见问题解答
  9. CSS强制英文换行
  10. 安全接口 interface --显示实现接口
  11. object-c 1
  12. Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(一)
  13. SQL Server 2008 Values 新用途
  14. DB2中的系统表SYSIBM.SYSDUMMY1
  15. .net Work Flow 4.0
  16. ContentProvider的使用
  17. input失效后,怎么改变它默认就有的灰色
  18. js精要之对象属性
  19. 扎实基础之从零开始-Nginx集群分布式.NET应用
  20. laravel中数据库在哪个文件中配置

热门文章

  1. 内置函数 strlen
  2. 作为有经验的程序员如果不懂Lambda表达式就说不过去了吧,建议收藏!!!
  3. Speed up Downloading Files on Linux
  4. spring中的组合模式
  5. Linux 硬盘与硬件管理
  6. centos7上用docker搭建简单的前后端分离项目
  7. sqli-labs lesson 26-27a
  8. PHP变量覆盖漏洞整理
  9. 谈谈Linux字符设备驱动的实现
  10. 超过Numpy的速度有多难?试试Numba的GPU加速