浅谈JavaScript 执行环境、作用域及垃圾回收


Posted in Javascript onMay 31, 2016

执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象。

全局执行环境是最外围的一个执行环境。根据JavaScript实现所在的宿主环境不同,表示执行环境的对象也不一样。在Web浏览器中,全局执行环境被认为是window对象。因此,所有的全局变量和函数都是作为window对象的属性和方法创建的。

变量对象:环境中定义的所有变量和函数都保存在这个对象中。

作用域链:当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。

活动对象:活动对象在最开始时只包含一个变量,即arguments对象。作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量对象来自下一个包含环境。这样一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象。

标识符解析:标识符解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级地向后回溯,直至找到标识符为止。

示例代码:

var color = "blue";
function changeColor() {
  if (color === "blue") {
    color = "red";
  } else {
    color = "blue";
  }
}
changeColor();

alert("Color is now " + color);

函数changeColor()的作用域链包含两个对象:它自己的变量对象(其中定义着arguments对象)和全局变量的变量对象。可以在函数内部访问变量color,就是因为可以在这个作用域链中找到它。

此外,在局部作用域中定义的变量可以在局部环境中与全局变量互换使用,示例:

var color = "blue";
function changeColor() {
  var anotherColor = "red";

  function swapColors() {
    var tempColor = anotherColor;
    anotherColor = color;
    color = tempColor;

    // 这里可以访问color、anotherColor和tempColor
  }

  // 这里可以访问color、anotherColor,不能访问tempColor
  swapColors();
} 

// 这里只能访问color
changeColor();

以上代码供涉及3个执行环境:全局环境、changeColor()的句柄环境和swapColors()的局部环境。

全局变量中有一个变量color和一个函数changeColor()。changeColor()的局部变量中包含了一个变量anotherColor和一个函数swapColors()函数,它可以访问全局变量中的color。swapColors()的局部变量中有一个变量tempColor。在swapColors()中可以访问全局变量中的color,也可以访问anotherColor变量,因为那两个环境是它的父执行环境。上面的例子的作用域链为:

  浅谈JavaScript 执行环境、作用域及垃圾回收

其中,内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。环境变量之间的联系是线性的、有次序的。每个变量只能向上级搜索作用域链,以查询变量和函数名,即首先在本作用于中查询变量或函数名,如果没有再向上一级作用域链查询,直到顶级作用域。但是任何环境都不能向下搜索作用域链而进入另一个执行环境。

函数参数也被当作变量来对待,因此其访问规则与执行环境中的其他变量相同。

1.延长作用域链

当执行流进入下列任何一个语句时,作用域链就会得到延长:

• try-catch语句的catch块

• with语句

这两个语句会在作用域的前端添加一个变量对象。

对于with语句来说,会将指定的变量添加到作用域链中。对catch语句来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。

举个例子:

function buildUrl() {
  var qs = "?debug=true";
  with(location) {
    var url = href + qs;
  }
  return url;
}

with语句接收的是location对象,因此其变量对象中包含了location对象的所用属性和方法,这个变量对象被添加到作用域链的前端。当在with语句中引用变量href时(实际引用的是location.href),可以在当前环境变量中找到。当引用变量qs时,引用的是buildUrl()中定义的那个变量,该变量位于函数环境变量对象中。至于with语句内部,则定义了一个名为url的变量,因而url就成了函数执行环境的一部分,可以作为函数的值被返回。

2.没有块级作用域

在JavaScript中,封闭的花括号没有自己的作用域。看下面的代码:

 

if(true) {
  var color = "blue";
}
alert(color);  // "blue"

在JavaScript中,if/for语句创建的变量声明会将变量添加到当前的执行环境中。例如:

for(var i = 0; i < 10; i++) {
  doSomething(i);
}
alert(i);// 10

垃圾回收

与Java相似,JavaScript也具有自动回收垃圾机制。执行环境会负责管理代码执行过程中使用的内存。在编写程序时,不需要关系内存使用问题,所需内存的分配以及无用内存的回收完全实现了自动管理。垃圾回收机制的原理就是:找出不再继续使用的变量,然后释放其占用的内存。为此,垃圾回收器会按照固定的时间间隔(或代码执行中预定的收集时间),周期性地进行这一操作。

在做垃圾回收之前,必须判断该资源是否无用,对于不再使用的变量打上标记,以备将来回收其内存。用于标识无用变量的策略通常有两个实现。

1 标记清除

JavaScript中最常用的垃圾收集方式是标记清除。当变量进入环境,就将变量标记为“进入环境”;当变量离开环境时,则将变量标记为“离开环境”。垃圾回收器在运行的时候会给所用变量都加上标记。然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,最后垃圾回收器完成内存清除工作,销毁带标记的值并回收它们所占的内存空间。

2.引用计数

引用计数是指跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次数加1。相反,如果包含这个值引用的变量又取得了另一个变量,则这个值的引用次数减1。当这个变量的引用次数为0时,则说明没有办法再引用这个变量了,因而就可以将其内存空间回收回来。当垃圾回收器下次运行时就会回收这些引用次数为零的值占用的内存。

引用计数会产生的一个问题就是可能会导致循环引用。例如:

function problem() {
  var objA = new Object();
  var objB = new Object();

  objA.someOtherObj = objB;
  objB.someOtherObj = objA;
}

上面的例子中,objA和objB通过属性相互引用。函数执行完成后,objA和objB将继续存在,它们的引用计数不会为0。这种情况会导致objA和objB所占的内存无法回收。

以上这篇浅谈JavaScript:执行环境、作用域及垃圾回收就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
浅谈JavaScript中面向对象技术的模拟
Sep 25 Javascript
JS截取字符串常用方法整理及使用示例
Oct 18 Javascript
js加载读取内容及显示与隐藏div示例
Feb 13 Javascript
原生js实现复制对象、扩展对象 类似jquery中的extend()方法
Aug 30 Javascript
javascript自动生成包含数字与字符的随机字符串
Feb 09 Javascript
javascript Slip.js实现整屏滑动的手机网页
Nov 25 Javascript
jQuery leonaScroll 1.1 自定义滚动条插件(推荐)
Sep 17 Javascript
js实现带三角符的手风琴效果
Mar 01 Javascript
JS实现的自动打字效果示例
Mar 10 Javascript
JS模拟超市简易收银台小程序代码解析
Aug 18 Javascript
Angular封装搜索框组件操作示例
Apr 25 Javascript
jquery实现图片无缝滚动 蒙版遮蔽效果
Jan 11 jQuery
页面get请求 中文参数方法乱码问题的快速解决方法
May 31 #Javascript
Bootstrap表单布局样式代码
May 31 #Javascript
jQuery使用经验小技巧(推荐)
May 31 #Javascript
JavaScript知识点总结(十)之this关键字
May 31 #Javascript
JavaScript知识点总结(六)之JavaScript判断变量数据类型
May 31 #Javascript
JavaScript知识点总结(五)之Javascript中两个等于号(==)和三个等于号(===)的区别
May 31 #Javascript
JavaScript知识点总结(四)之逻辑OR运算符详解
May 31 #Javascript
You might like
php中的数组操作函数整理
2008/08/18 PHP
简单的php中文转拼音的实现代码
2014/02/11 PHP
php Imagick获取图片RGB颜色值
2014/07/28 PHP
PHP中Session可能会引起并发问题
2015/06/26 PHP
PHP函数用法详解【初始化、嵌套、内置函数等】
2020/06/02 PHP
JQuery DataTable删除行后的页面更新利用Ajax解决
2013/05/17 Javascript
JavaScript截取字符串的Slice、Substring、Substr函数详解和比较
2014/03/20 Javascript
JS判断、校验MAC地址的2个实例
2014/05/05 Javascript
2014年50个程序员最适用的免费JQuery插件
2014/12/15 Javascript
JS+CSS实现简单滑动门(滑动菜单)效果
2015/09/19 Javascript
详解Node.js如何开发命令行工具
2016/08/14 Javascript
jq实现左滑显示删除按钮,点击删除实现删除数据功能(推荐)
2016/08/23 Javascript
js 输入框 正则表达式(菜鸟必看教程)
2017/02/19 Javascript
详解用vue.js和laravel实现微信支付
2017/06/23 Javascript
解决Js先触发失去焦点事件再执行点击事件的问题
2018/08/30 Javascript
使用layer模态框给新页面传值的方法
2019/09/27 Javascript
Js图片点击切换轮播实现代码
2020/07/27 Javascript
详解JavaScript数据类型和判断方法
2020/09/04 Javascript
Python3.2中Print函数用法实例详解
2015/05/19 Python
使用Python3制作TCP端口扫描器
2017/04/17 Python
Python字符串内置函数功能与用法总结
2019/04/16 Python
如何使用Python自动控制windows桌面
2019/07/11 Python
Django框架基础模板标签与filter使用方法详解
2019/07/23 Python
python使用sklearn实现决策树的方法示例
2019/09/12 Python
Python实现桌面翻译工具【新手必学】
2020/02/12 Python
python实现word文档批量转成自定义格式的excel文档的思路及实例代码
2020/02/21 Python
python 实现客户端与服务端的通信
2020/12/23 Python
python单例模式的应用场景实例讲解
2021/02/24 Python
美国单身专业人士在线约会网站:EliteSingles
2019/03/19 全球购物
大学应届毕业生个人求职信
2013/09/23 职场文书
办公室前台岗位职责
2014/01/04 职场文书
平面设计专业大学生职业规划书
2014/03/12 职场文书
行政执法作风整顿剖析材料
2014/10/11 职场文书
幼儿园老师新年寄语2015
2014/12/08 职场文书
十二月早安励志心语大全
2019/12/03 职场文书
HTML5+CSS+JavaScript实现捉虫小游戏设计和实现
2021/10/16 HTML / CSS