变量、作用域和内存问题

109 阅读3分钟

这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战

基本类型和引用类型的值

  • 基本类型:简单的数据段(UndefinedNullBooleanStringNumber
  • 引用类型:可能由多个值构成的对象(ArrayObjectFunction
类型检测

typeof 操作符是确定一个变量是 StringNumberBooleanUndefined 的最佳工具,而变量的值是一个对象或者 Null,则会返回 object;检测引用类型的工具使用 instanceof 操作符,返回类型是布尔值。

var a = "nickname";
var b = 20;
var c = [1, 2, 3];

console.log(typeof a); // string
console.log(typeof b); // number
console.log(typeof c); // object
console.log(c instanceof Array); // true

执行环境及作用域

执行环境定义了变量或者函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个和它相关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。

全局执行环境所在的宿主环境不同,表示的执行环境的对象也不一样。如在 web 浏览器中,全局执行环境被认为是 window 对象。

每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。函数执行后,栈将其环境弹出,把控制权返回给之前的执行环境。

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

垃圾收集

JavaScript 的执行环境会负责管理代码执行过程中使用的内存,具有自动垃圾收集机制。不用再关心内存使用问题。垃圾收集机制原理是按照固定的时间间隔或者代码执行中预定的收集时间找出那些不再继续使用的变量,释放其占用的内存。

用于垃圾收集器会对于不再有用的变量打上标记,用于将来收回其占用的内存。用于标识无用变量的策略通常有两种:

1. 标记清除

标记清除:当变量进入环境,如声明一个变量的时候,就将这个变量标记为“进入环境”。而当变量离开环境时,将其标记为“离开环境”。垃圾收集器会在运行的时候给存储在内存中的所有变量加标记,然后,去掉环境中的变量以及被环境中的变量引用的变量的标记。之后再被加上标记的变量视为准备删除的变量。最后,垃圾收集器完成内存清除工作,销毁带标记的值和回收被占用的内存空间。

2. 引用计数

引用计数:跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数是1,如果同一个值又被赋给另一个变量,则该值得引用次数加1。包含对这个值引用的变量又取得了另一个值,这个值的引用次数减1.当这个值的引用次数变成0时,说明没有办法再访问这个值了。当垃圾收集器再运行时,会释放那些引用次数为零的值所占用的内存。

管理内存

虽然开发人员一般不必操心内存管理的问题。但是内存限制问题会影响调用栈以及在一个线程中能够同时执行的语句数量。优化内存占用的最佳方式是为执行中代码只保存必要的数据。一旦数据不再有用,最好通过将其值设置为 null 来释放。