JavaScript

JS的解析过程、作用域及作用域链、垃圾回收机制

字数:1464    阅读时间:8min
阅读量:652

JS是一门编译语言,是在浏览器运行时候开始编译的,浏览器是如何解析我们的 JS的呢?JS的解析过程可分为: 语法检查阶段执行阶段

  • 语法分析:
    • 词法分析:把js的字符流转换成标记流
    • 语法分析: 把标记流产生的记号按照ECMAScript标准生成语法树 (把收集到的信息存储到数据类型中)
  • 执行阶段:
    • 预解析:
      • 创建执行上下文;变量对象(变量声明,函数声明,参数),作用域链(变量对象以及所有父级作用域),this
      • 变量对象活动对象填充数值(权重:函数参数>函数声明>变量声明)
        • 函数参数:执行上下文变量对象的一个属性,属性名称是这个形参,值是实参的,没有传递参数值就是undefined
        • 函数声明:执行上下文变量对象的一个属性,属性名和属性值都是是函数对象创建出来的,如果变量对象已经包含了与他相同名字的属性,则会替换它的值
        • 变量声明:执行上下文变量对象的一个属性,属性名就是这个变量名,值是undefined,如果变量名和参数名函数声明名重复,则该声明会被忽略,但是其赋值操作不会被忽略
    • 执行阶段
      • 预解析之后就是js真正的执行阶段了,js引擎会一行一行读取运行代码,变量对象和活动对象都被赋予真是的值,如果函数没有被调用则里边的变量永远都是undefined

我们为了方便存储和读取数据,往往会将不同的数据存放在不同的地方,这些存放数据的地方就可以叫做作用域(作用域就是存储和读取的一套规则),JS中没有只有全局作用域和函数作用域(ES6才引入块级作用域)

  • 作用域
    • 创建: js采用的是静态作用域(词法作用域),也就是在词法分析的时候就把作用域确定好了,之后是不能改变的(evel()和with()可以改变但是消耗性能)
    • 特点:作用域可以嵌套但是不能重叠(重叠就覆盖)
    • 定义:是一种分类存储数据规则
  • 作用域链
    • 创建:作用域链是一个数组 [[Scope]] :[当前变量对象,父级上下文变量对象...];其中当前变量对象是在函数执行之前创建的,第二部分是在函数声明时就已经确定的
    • 特点:变量查找是只能一级一级向上找,不能向下找(子级能访问父级的变量,父级不能访问子级的变量)
    • 定义:是 一种变量查找的规则

垃圾回收机制:
  我们知道我们的浏览器内存是有限的,随着js中的变量、对象增多势必会对浏览器造成很大压力,那么我们就需要在使用完这些变量、对象之后就给他们清楚除掉;很幸运的是我们的JS有一套自己的垃圾回收机制,在我们不需要这些变量和对象的时候会自动帮我们清除他们
  JS使用的清除方式是标记清除:当变量进入到执行环境中时,标记为"进入环境",在离开执行环境时标记位"离开环境";当变量为"离开环境"时就会被垃圾回收机制给清除

  • 不会被清除的情况
    • 全局作用域变量:全局作用域的变量在浏览器打开的时候会一直被标记为"进入环境",只有在关闭浏览器的时候才会被标记为"离开环境"才能被清除;所以应该尽量减少定义全局变量或者使用严格模式
    • 闭包:当调用闭包的那个对象一直都没有被清除(比如在全局调用闭包,或者异步调用闭包的时候),那么闭包里的变量就一直存在不会被清除,做法是在调用完之后把调用闭包的那个对象给清空为'null'
    • 定时器和回调:没有清除定时器,那里边的变量就会一直存在不会被销毁;能清除的定时器一定要清除
    • Dom元素的引用:我们通常会将Dom引用放进一个数组或者对象中,当我们不需要这个对象了把这个对象删除了,但是这个对象的引用还是依然存在的,这个时候就需要手动将这个Dom的引用删除:整个对象为'null'或者删除这个属性
野生小园猿
励志做一只遨游在知识海洋里的小白鲨
查看“野生小园猿”的所有文章 →

发表评论

邮箱地址不会被公开。

相关推荐