本文参考链接:https://www.jianshu.com/p/cf47bc0bf2ab

一、先搞懂两个东西:堆和栈

栈由操作系统自动分配释放,用于存放函数的参数值、局部变量等一些基本的数据类型,其操作方式类似于数据结构中的栈

堆用于存放对象(引用数据类型),一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收。分配方式类似于链表。

栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放。

堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。

栈: 在函数调用时,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。

当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向函数的返回地址,也就是主函数中的下一条指令的地址,程序由该点继续运行。

堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排。

 1、栈

 函数中定义的局部变量按照先后定义的顺序依次压入栈中,也就是说相邻变量的地址之间不会存在其它变量。栈的内存地址生长方向与堆相反,由高到底,所以后定义的变量地址低于先定义的变量。

 2、堆

var car1 = {
  name: 'huruqing',
  money: 100000000
}
var car2 = car1;
car2.money = 1000;
console.log(car1.money === car2.money); //true 1000
var obj1 = {
  a: 2
}
var obj2 = {
  a: 2
}
console.log(obj1 === obj2); // false

var arr1 = [];
var arr2 = [];
console.log(arr1 === arr2); // false

 栈相比于堆,在程序中应用较为广泛,最常见的是函数的调用过程由栈来实现,函数返回地址、EBP、实参和局部变量都采用栈的方式存放。虽然栈有众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,主要还是用堆。

二、事件循环模型

 解释:

1. 所有代码分类
  * 初始化执行代码(同步代码): 包含绑定dom事件监听, 设置定时器, 发送ajax请求的代码
  * 回调执行代码(异步代码): 处理回调逻辑
2. js引擎执行代码的基本流程:
  * 初始化代码===>回调代码
3. 模型的2个重要组成部分:
  * 事件管理模块(定时器/DOM事件/Ajax)
  * 回调队列
4. 模型的运转流程
  * 执行初始化代码, 遇到同步代码立即执行,遇到异步任务将事件回调函数交给对应模块管理(定时器/DOM事件/Ajax)
  * 当事件发生时, 管理模块会将回调函数及其数据添加到回调列队中
  * 只有当初始化代码执行完后(可能要一定时间), 才会遍历读取回调队列中的回调函数执行

 同步任务和异步任务会进入不同的执行环境,所有的同步任务都会进入到主执行栈,所有的异步任务都会进入到任务队列,直到主执行栈的任务执行完毕才会执行任务队列的异步任务,这一过程的不断重复就是事件循环。

举例子:

function fn1() {
    console.log('fn1()')
  }
  fn1()
  document.getElementById('btn').onclick = function () {
    console.log('点击了btn')
  }
  setTimeout(function () {
    console.log('定时器执行了')
  }, 2000)
  function fn2() {
    console.log('fn2()')
  }
  fn2()

推荐几篇有利于帮助我们更好的理解事件循环的文章

https://www.cnblogs.com/yugege/p/9598265.html

https://segmentfault.com/a/1190000015317434

https://www.cnblogs.com/cangqinglang/p/8967268.html

12-14 19:44
查看更多