执行环境与作用域

执行环境及作用域

执行环境

简单一点说程序执行到哪,那一块所属的范围就是执行环境,在那一块范围内,变量又能访问哪些数据

  • 执行环境定义了变量或函数有权访问的其他数据,并且每个执行环境都有一个变量对象,里面存了这个执行环境中定义的所有变量或函数
  • 一般分为全局执行环境和局部执行环境,全局一般就是window(浏览器),局部就是函数内部
  • 每个执行环境运行完,相应的变量对象及其中的变量和函数皆销毁。

作用域链

换个方向思考

  • 执行的过程中,解析器会遇到变量和函数,那么这些变量函数是哪定义的呢?要怎么找怎么确定?

  • 是不是毫无顺序的乱找?

看例子

1
2
3
4
5
6
7
8
9
10
11
12
13
var a = 1;//ex1
function H() {
var b = 2; //ex2
console.log(a);//ex2
var c = function F() {
var great = 'yes';//ex4
console.log(b + great);//ex4
}
}
function G() {
var a = 1 //ex3
}
H();//ex1

每一个执行环境都有一个变量对象,JS执行过程中,会将当前执行环境对应的对象压入栈中,完了就扔出去。

当执行到某一个环境时,会创建一个作用域链,这个链最前面是当前环境变量对象,最后面是全局环境变量对象

它只能从头,也就是本身的环境开始,一直往后面找直到找到为止.

比如:

  • 当在 ex2 中执行时,会生成一个作用域链: ex1 -> ex2

想找到变量a,就只能在 ex2 或者退到 ex1找,不允许进入 ex4,甚至是退到 ex1 又进到 ex3.因为作用域链就是这么规定的,

到这里就应该知道,执行环境变量对象是为了存储当前执行环境的所有变量,而为了知道这些变量代表什么?哪来的?有没有创建过?就需要通过作用域链去找,去识别,这样执行环境中的变量才算完整

延长作用域链

  • try-catch语句块的catch块
  • with语句

临时增加一个变量在作用域链顶端,但这个变量不是执行环境

就比如 执行环境1 -> 执行环境2 -> 变量

细看例子

1
2
3
4
5
6
7
8
9
var a = 1;//ex1
function H() {
var b = 2; //ex2
with(test) {
var c = test + 1;
}
return c; //ex2
}
H();//ex1

上述函数可以正确返回值,照理说应该不能啊,因为 with 语句里的东西外面访不到啊?

按作用域链规则来说确实不行,因为处在 ex2 的 return c 中的 c只能在ex2找,或者前后到 ex1,

但是记住作用域链是怎么找的?从最顶端开始~~,虽然执行是在 ex2,但是因为 with语句的作用就是临时增加一个变量对象在前面,开始找的时候就能找到

ex1 -> ex2 -> 变量c

所以这就是延长作用域链

没有块级作用域

比如 if 、for 语句

1
2
3
4
for(var i = 0; i < 10; i++) {
.....
}
console.log(i)//10

像C语言,Java,这里的 i 在外面访问肯定不是 10,但是JS没有块级作用域,这里的 i 就在 for语句外的环境里。

变量声明没有用var的话会被添加到全局环境中

垃圾回收

标记清除

函数申明变量时标记为进入环境,当执行完该函数时标位离开环境,当垃圾回收例程开始时,回收标记为离开环境的变量所占内存空间

引用计数

一个引用类型值赋给变量时,引用加1,同样的另一个变量也引用这个值则加1,反之曾经引用它的变量引用别的值是,它就减1

存在循环引用的问题

性能问题

垃圾回收是按一定机制或者条件来触发的,太频繁一些长期需要的值会被重复创建,太慢又会积攒太多空间。

管理内存

前提:因为计算机分配给浏览器的资源没有计算机上的软件多,所以虽有自动垃圾回收机制,但也要在代码中尽可能合理利用空间

将变量或对象设为 null ,在下次垃圾回收时会自动清除。适用大多数

文章作者: 努力向前
文章链接: https://greatiga.cn/2020/06/24/javaScript/executionContext/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 努力向前