执行环境及作用域
执行环境
简单一点说程序执行到哪,那一块所属的范围就是执行环境,在那一块范围内,变量又能访问哪些数据
- 执行环境定义了变量或函数有权访问的其他数据,并且每个执行环境都有一个变量对象,里面存了这个执行环境中定义的所有变量或函数
- 一般分为全局执行环境和局部执行环境,全局一般就是window(浏览器),局部就是函数内部
- 每个执行环境运行完,相应的变量对象及其中的变量和函数皆销毁。
作用域链
换个方向思考
执行的过程中,解析器会遇到变量和函数,那么这些变量函数是哪定义的呢?要怎么找怎么确定?
是不是毫无顺序的乱找?
看例子
1 | var a = 1;//ex1 |
每一个执行环境都有一个变量对象,JS执行过程中,会将当前执行环境对应的对象压入栈中,完了就扔出去。
当执行到某一个环境时,会创建一个作用域链,这个链最前面是当前环境变量对象,最后面是全局环境变量对象
它只能从头,也就是本身的环境开始,一直往后面找直到找到为止.
比如:
- 当在 ex2 中执行时,会生成一个作用域链: ex1 -> ex2
想找到变量a,就只能在 ex2 或者退到 ex1找,不允许进入 ex4,甚至是退到 ex1 又进到 ex3.因为作用域链就是这么规定的,
到这里就应该知道,执行环境变量对象是为了存储当前执行环境的所有变量,而为了知道这些变量代表什么?哪来的?有没有创建过?就需要通过作用域链去找,去识别,这样执行环境中的变量才算完整
延长作用域链
- try-catch语句块的catch块
- with语句
临时增加一个变量在作用域链顶端,但这个变量不是执行环境
就比如 执行环境1 -> 执行环境2 -> 变量
细看例子
1 | var a = 1;//ex1 |
上述函数可以正确返回值,照理说应该不能啊,因为 with 语句里的东西外面访不到啊?
按作用域链规则来说确实不行,因为处在 ex2 的 return c 中的 c只能在ex2找,或者前后到 ex1,
但是记住作用域链是怎么找的?从最顶端开始~~,虽然执行是在 ex2,但是因为 with语句的作用就是临时增加一个变量对象在前面,开始找的时候就能找到
ex1 -> ex2 -> 变量c
所以这就是延长作用域链
没有块级作用域
比如 if 、for 语句
1 | for(var i = 0; i < 10; i++) { |
像C语言,Java,这里的 i 在外面访问肯定不是 10,但是JS没有块级作用域,这里的 i 就在 for语句外的环境里。
变量声明没有用var的话会被添加到全局环境中
垃圾回收
标记清除
函数申明变量时标记为进入环境,当执行完该函数时标位离开环境,当垃圾回收例程开始时,回收标记为离开环境的变量所占内存空间
引用计数
一个引用类型值赋给变量时,引用加1,同样的另一个变量也引用这个值则加1,反之曾经引用它的变量引用别的值是,它就减1
存在循环引用的问题
性能问题
垃圾回收是按一定机制或者条件来触发的,太频繁一些长期需要的值会被重复创建,太慢又会积攒太多空间。
管理内存
前提:因为计算机分配给浏览器的资源没有计算机上的软件多,所以虽有自动垃圾回收机制,但也要在代码中尽可能合理利用空间
将变量或对象设为 null ,在下次垃圾回收时会自动清除。适用大多数