JS006. 详解自执行函数原理与数据类型的快速转换 (声明语句、表达式、运算符剖析)
今天的主角:
| Operator | Description | 
| 一元正值符 " + "(MDN) | 一元运算符, 如果操作数在之前不是number,试图将其转换为number。 | 
| 
 圆括号运算符 " () "(MDN)  | 
圆括号运算符由一对圆括号组成,包裹表达式和子表达式用来覆盖常规的运算符优先级(MDN),达到低优先级的表达式比高优先级的表达式更早运算。 | 
一元正值符 - " + "

? 为什么图例 - 3中 +'1.22' + 1.5 = 2.71999999… ? 查看我的另一篇文章:深入探讨带浮点数运算丢失精度问题(二进制的浮点数存储方式)
首先区分如 let x = '1.20' 是作为变量声明被浏览器解析,包括 function / let / var / const / class 等等这些都是作为 声明语句 被解析。
浏览器预解析到声明语句,则会将其存入堆栈区并为其分配存储空间。
而 运算符 - 一元正值符(+) 的作用是 声明语句 --> 表达式语句(“ 使某件事发生 ” 的计算带有副作用的表达式)。
它为什么带有副作用:

除了基本数据类型外,任何数据都会被正值运算符 “ + ” 转换成Number类型数据,包括Object或Array的引用如
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 -
JS006. 详解自执行函数原理与数据类型的快速转换 (声明语句、表达式、运算符剖析)的更多相关文章
- javascript模块化编程-详解立即执行函数表达式IIFE
		
一.IIFE解释 全拼Imdiately Invoked Function Expression,立即执行的函数表达式. 像如下的代码所示,就是一个匿名立即执行函数: (function(windo ...
 - 详解立即执行函数(function(){}()),(function(){})()
		
要知道这几种写法之间的区别,我们要先聊些题外话——js中函数的两种命名方式,即表达式和声明式. 函数的声明式写法为:function foo(){/*...*/},这种写法会导致函数提升,所有func ...
 - [转帖]万字详解Oracle架构、原理、进程,学会世间再无复杂架构
		
万字详解Oracle架构.原理.进程,学会世间再无复杂架构 http://www.itpub.net/2019/04/24/1694/ 里面的图特别好 数据和云 2019-04-24 09:11:59 ...
 - 淘宝JAVA中间件Diamond详解(2)-原理介绍
		
淘宝JAVA中间件Diamond详解(二)---原理介绍 大家好,通过第一篇的快速使用,大家已经对diamond有了一个基本的了解.本次为大家带来的是diamond核心原理的介绍,主要包括server ...
 - SpringCloud 详解配置刷新的原理 使用jasypt自动加解密后 无法使用 springcloud 中的自动刷新/refresh功能
		
之所以会查找这篇文章,是因为要解决这样一个问题: 当我使用了jasypt进行配置文件加解密后,如果再使用refresh 去刷新配置,则自动加解密会失效. 原因分析:刷新不是我之前想象的直接调用conf ...
 - ggplot2作图详解:入门函数qplot
		
ggplot2作图详解:入门函数qplot ggplot2的功能不用我们做广告,因为它的作者Hadley Wickham就说ggplot2是一个强大的作图工具,它可以让你不受现有图形类型的限制,创 ...
 - [转帖]详解Linux系统inode原理--硬链接、软链接、innodb大小和划分等
		
详解Linux系统inode原理--硬链接.软链接.innodb大小和划分等 原创 波波说运维 2019-07-17 00:03:00 https://www.toutiao.com/i6713116 ...
 - RocketMQ详解(一)原理概览
		
专题目录 RocketMQ详解(一)原理概览 RocketMQ详解(二)安装使用详解 RocketMQ详解(三)启动运行原理 RocketMQ详解(四)核心设计原理 RocketMQ详解(五)总结提高 ...
 - jQuery的deferred对象详解  jquery回调函数
		
http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html jQuery的 ...
 
随机推荐
- canal同步异常:当表结构变化时,同步失败
			
场景 canal 同步Mysql一段时间后突然失败,报如如下错误: 2021-08-06 16:16:51.732 [MultiStageCoprocessor-Parser-Twt_instance ...
 - POJ 1190 生日蛋糕题解
			
题目地址:http://poj.org/problem?id=1190 一道很有趣的搜索题--主要是剪枝-- 我弄了5个剪枝: 1.当前剩余层数>=上层半径,剪掉 2.当前剩余层数>=上层 ...
 - Java互联网架构师系统进阶课程 (一)【享学】
			
2.线程的并发工具类 Fork-Join 什么是分而治之? 规模为N的问题,N<阈值,直接解决,N>阈值,将N分解为K个小规模子问题,子问题互相对立,与原问题形式相同,将子问题的解合并得到 ...
 - 离线webpack创建vue 项目
			
参考地址: https://blog.csdn.net/feinifi/article/details/104578546 画重点: // 需要带上参数--offline表示离线初始化. --offl ...
 - 来看看是什么原因导致生产服上的系统CPU高的?
			
我们可能会遇到生产服务器CPU很高的问题,有时候能确定是哪个进程,但是不知道这个进程都在干什么,所以也无从下手,无法解决问题.只能不断的重启,重启等. 最近也看了[一线码农]的一些教程,觉得都很不错, ...
 - appium自动化测试(5)-一些pyhon操作
			
1.套件的问题 将所有的测试用例加进去,会一个个执行,用于用例名字没有规范test开头的时候 def suite(): suite = unittest.TestSuite suite.addTest ...
 - 基于AOP和HashMap原理学习,开发Mysql分库分表路由组件!
			
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 什么?Java 面试就像造火箭 单纯了! 以前我也一直想 Java 面试就好好面试呗 ...
 - STM32—TIMx输出PWM信号驱动MG996R舵机
			
文章目录 一.前言 二.MG996R舵机简介 三.TIM定时器简介 四.通用定时器TIMx 1.TIMx主要功能 2.TIMx框图 3.计数单元 4.时钟选择 5.输出比较PWM 五.TIM3输出双路 ...
 - Kurento实战之四:应用开发指南
			
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
 - VS+Qt+Halcon——显示图片,实现鼠标缩放、移动图片
			
摘要 本篇博文记录一下,用VS+Qt+Halcon实现对图片的读取以及鼠标缩放,移动(鼠标事件调用了halcon自带的算子)的过程.以及遇到的坑..... 先来看一下动态效果图: 主要控件: 添加一个 ...