函数堆
- 把函数体中的代码当做字符串存储到堆中"代码字符串" => 创建函数不执行,函数没用
- 函数也是对象,也有自己的键值对
- name
- length
- prototype
- __ proto __
作用域[[scope]]
创建函数的时候,就定义了函数的作用域 => 当前创建函数所在的上下文
函数执行
- 定义函数设置的是形参,执行函数传递的是实参。
- 目的: 让之前存储在堆中的代码字符串执行 => 代码执行就要有自己的执行环境
1 形成一个全新的私有上下文EC(FN),供代码执行(进栈)
- ① 把全局上下文放到栈的底部
- ② 新进来的上下文放到栈顶部
2 形成私有变量对象AO(FN)存储私有变量
2.1 初始化作用域链
- 组成
- 自己所在的上下文
- 函数的作用域
- 作用
- 日后在私有上下文代码执行的时候,遇到一个变量,我们首先看是否为自己的私有变量(在自己的变量对象中有没有),是私有的,操作的都是自己的,不是私有的,按照作用域链找上级上下文中的…………一直找到全局上下文为止
2.2 初始化THIS指向 : window
2.3 初始化实参集合: arguments
2.4 形参赋值 : 形参 = 实参
2.5 变量提升
2.6 代码执行
3 正常情况下,代码执行完,私有上下文会出栈(出栈后被释放,以此节约栈内存的空间);但是有特殊情况,如果当前私有上下文中的某个东西(一般是一个堆)被上下文外的事物占用了,则上下文不会再出栈释放,也就是形成不销毁的上下文
浏览器垃圾回收机制(自己内部处理)
[谷歌等浏览器是“基于引用查找“来进行垃圾回收的]
- 开辟的堆内存,浏览器自己默认会在空闲的时候,查找所有内存的引用,把那些不被引用的内存释放掉
- 开辟的栈内存(上下文)一般在代码执行完都会出栈释放,如果遇到上下文中的东西被外部占用,则不会释放
[IE等浏览器是“基于计数器”机制来进行内存管理的]
- 创建的内存被引用一次,则计数1,在被引用一次,计数2... 移除引用减去1... 当减为零的时候,浏览器会把内存释放掉 =>真实项目中,某些情况导致计数规则会出现一些问题,造成很多内存不能被释放掉,产生“内存泄漏”(ie);查找引用的方式如果形成相互引用,也会导致“内存泄漏"(chrome)
let obj = {name:"yang"}
let op = obj
obj = null
op =null