记录一些比较有意思的话题。
new操作符的工作原理
我们都知道 new 运算符是用来实例化一个类,从而在内存中分配一个实例对象。
PS:这里我先说明一下直接执行 Person 会返回 undefined,new Person(…) 会返回一个对象(即我们的this对象)。
调用构造函数实际上会经历以下4个步骤
(1) 创建一个新对象
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象即类的实例)
(3) 执行构造函数中的代码(即为这个新对象添加属性)
(4) 返回新对象
如果不明白,请看前辈整理的文章
JavaScript内部属性[[Scope]]与作用域链的理解
[[Scope]]属性
每一个 function 声明时都会有一个内部属性 [[Scope]],例如声明 foo 函数会创建一个 foo.[[Scope]] 属性
执行环境
在函数执行时,会创建一个叫做执行环境/执行上下文(execution context,下文均用EC表示)的内部对象(独一无二)。
执行环境有以下特点
函数每次执行时的执行环境独一无二
多次调用同一函数就多次创建执行环境
并且函数执行完毕后,执行环境就会被销毁
案列分析
这里我们来看一个稍微复杂一点的场景
foo函数在预编译阶段创建了bar函数,于是bar函数创建了属性[[Scope]],包含bar被创建的作用域中对象的集合,也就是复制了foo.EC
所以我们可以得到
PS:由于bar函数是在foo函数执行时创建的,所以bar[[Scope]]=foo.EC
bar函数执行,过程同foo函数执行相近,整理出 bar.EC
作用域链
js引擎就是通过作用域链的规则来进行变量查找(准确的说应该是执行上下文的作用域链)
查找过程就拿上面的代码来说,比如说我在bar函数执行console.log(a);
那么bar函数执行时,js引擎想要打印a,于是就去作用域链上查找
第一层AO没有(bar运行时产生的)
第二层AO没有(foo运行时产生的)
第三层GO找到了变量a (foo定义是a为undefined,预编译时a被赋值为1)
于是返回了变量a的值
如果在bar函数中在创建一个der函数,der的EC又会是怎么样呢?读者自行脑补吧(大体思路类似)
[[Scope]]与作用域链
defer和async
四种组合关系
<script src="script.js"></script>
没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。
<script async src="script.js"></script>
有 async,加载和渲染后续文档元素的过程将和 script.js 的加载并行进行,且并立即执行。
<script defer src="script.js"></script>
有 defer,加载和渲染后续文档元素的过程将和 script.js 的加载并行进行,但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。
<script defer async src="script.js"></script>
同时存在时,async生效。
defer和async 共同点
defer 和 async 在内联脚本无作用。
在下载时和与HTML解析异步的,执行时阻塞HTML解析(包括没有defer 和 async属性的场景)。
defer和async的区别
async异步下载后立即执行(可能不按下载顺序执行,适用于无任何依赖的脚本)。
defer异步下载后等文档完成解析后,触发 DOMContentLoaded 事件前执行(安下载顺序执行,适用于有依赖关系的脚本)。
PS:CSS并行下载,JS串行下载,相对于HTML解析来说。
defer和async的区别
PWA
具体功能
可以添加至主屏幕
实现离线缓存功能
实现了消息推送
相关技术
App Manifest
Service Worker
Push && Notification(push: server 将更新的信息传递给 SW notification: SW 将更新的信息推送给用户)
讲讲PWA
jsEvent Loop机制
在JavaScript中,任务被分为Task(又称为MacroTask,宏任务)和MicroTask(微任务)两种。
MicroTask
process.nextTick(node独有), Promises, Object.observe(废弃), MutationObserver
MacroTask
script(同步代码), setTimeout, setInterval, setImmediate(node独有), I/O, UI rendering
执行顺序
script(同步代码) -> MicroTask -> MacroTask
在执行上面代码时有产生了一些 MicroTask 和 MacroTask 会挂起,在一下次Event Loop再触发,以此类推。
可以看看我之前的博客
通用 curry 实现
|
|
通用的 compose 的实现
|
|