JavaScript的变量、作用域、内存

date
May 13, 2020
slug
hmpptoum
status
Published
tags
JavaScript
summary
type
Post
 

基本类型和引用类型的值

  • 基本类型:指简单的数据段,有 Undefined、Null、Number、Boolean、String,是按值访问的,可操作保存变量种的实际值。
  • 引用类型:指可能有多个值构成的对象,操作对象时是操作对象的引用,而不是实际的对象。
    • 当复制保存着对象的变量时,操作的是对象的引用。为对象添加属性时,操作的是实际对象。
有下面的区别:
  • 均可动态添加属性(即不会报错),但基本类型的属性会被自动忽略,访问时返回 undefined。
  • 基类类型复制是创建副本,引用类型是创建的指针副本,但指向的是同一个堆对象。
JavaScript 函数调用时,都是按值传递参数,所以函数的参数是一个函数的局部变量,这时就要参照上面区别第二点。

执行环境及作用域

执行环境(execution context)定义了变量或函数有权访问的其他数据,决定了它们各自行为。每个环境中都有一个与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。 全局执行环境是外围的执行环境。根据宿主环境不同,执行环境也不一样。
用户代码无法访问这个对象,但解析器在处理数据时会使用它。
每个函数都有自己的执行环境。函数环境在函数执行时被推入环境栈中,函数执行后被栈弹出,且把控制权交给之前的执行环境。
代码在环境中执行时,会创建变量对象的一个 作用域链 ,其目的是保证当前执行环境有权访问所有能访问的变量和函数的有序访问。如果这个环境是函数,则将其活动对象(activation object)作为变量对象。
标识符解析是沿着作用域一级一级地往上搜索标识符的过程,直到找到标识符为止(如果找不到通常会导致错误发生)。
var color = "blue";function changeColor() {  if (color === "blue") {    color = "red";  } else {    colort = "blue";  }}changeColor();console.log(color);
在例子中,changeColor()的作用域包含两个环境对象:它自己的变量对象(有 arguments 对象)和全局变量对象,在内部能访问 color 的原因就是可以在作用域链中找到它。
重要,JavaScript 没有块级作用域!只有函数作用域、全局作用域。不像其他类 C 语言,JavaScript 里花括号封闭里的代码存在变量提升,如 for 语句表达式中定义的变量。

垃圾回收

垃圾回收机制的原理很简单,就是找出那些不再继续使用的变量,然后释放其内存。垃圾收集器会按照固定时间间隔周期性执行垃圾回收。
  • 标记清除(mark-and-sweep):进入环境标记一次,离开环境标记一次。垃圾收集器会存储所有变量,去掉环境中的变量和被环境中变量引用的变量,其他的均视为准备删除的变量。
  • 引用计数(reference counting):被引用+1,解除引用-1。但是存在循环引用的问题,A 引用 B,B 引用 A。
使用最少的内存可以获得更好性能。所以一旦数据不再有用,最好是将值设为 null 来释放其引用,这叫做解除引用(dereferencing)。局部变量会在离开环境时自动被解除引用,解除引用的目的是让值脱离环境,以便垃圾收集器下次运行时将其收回。

© 刘德华 2020 - 2023