关于JS数据的存储,有两个很重要的方面,一是数据的存储方式 ,二是作用域与作用域链。
它们都影响着数据的正确使用,所以是JS必须弄懂的知识块。
数据的存储和数据的表达、数据的运算、数据的流程一起,并称为JS的数据四部曲。
数据的存储方式
只要是数据,最终都会在内存中存放,而JS中的数据在内存中有两种存放形式:值存放 和引用存放。
所谓值存放,就是在内存中存放一个具体的值。
所谓引用存放,就是在内存中存放一个地址,这个地址相当于一个引用,会指向内存的另外一块区域,那块区域才是真正的数据具体值的存放地。
基础数据类型的数据会使用值存放的形式,引用数据类型(即Object)的数据会使用引用存放的形式。
在JS内部,具体是这样实现的,当解析JS代码的时候,如果遇到{},即引用数据类型的数据时,就会开辟一块内存空间用于存储它的真实值,另外再开辟一块空间用于存放变量和值,后者放着引用,指向之前开辟的内存空间。
所以在JS中有个非常特殊的现象是,如下代码中,b重新赋值不会影响a的值,但d重新赋值会影响c的值,因为前者会开辟两块存放真实值的空间,后者虽然会开辟两块地址空间,但只会开辟一块真正存放值的引用空间,改变任何一个值都会影响这块引用空间,从而影响其它的值。
js
let a = b = 1;
let c = d = { name:'Bob' }
作用域与作用域链
JS中有三种作用域:1.全局作用域 2.函数作用域 3.块级作用域。
顾名思义,它们分别指的是变量声明是在全局范围内,还是函数范围内,还是{}块范围内起作用的,在全局声明的变量属于全局作用域,在函数内声明的变量属于函数作用域,在if、for等语句的{}块内声明的变量属于块作用域,特别最后一种只能是由let或const声明的变量,而var声明的变量不在块作用域内。
作用域之间存在着并列 和嵌套 关系,最外层是全局作用域,其内部并列、嵌套着函数作用域和块作用域,这样就形成了作用域链的关系,JS引擎会尝试在当前作用域去寻找变量,如果没找到,再到它的上层作用域寻找,以此类推直到全局作用域,如果最后都没找到,那就报错了。
总结
JS不提供内存管理接口,它是在创建变量时自动分配内存,并且在不使用它们时"自动"释放,即垃圾回收机制是自动的。
所以JS的内存管理是比较简单的,我们只需要关注如何创建变量即可,而本文就具体讲解了在哪里创建变量,它的作用域,以及创建的不同类型的变量在内存中的存在方式。