4.1基本类型和引用类型的值
ECMAScript变量可能包含两种不同数据类型的值 基本类型值 和 引用类型
值。
基本类型值:简单的数据段
引用类型值:可能由多个值构成的对象
将一个值赋给变量时,解析器必须确定这个值是基本数据类型还是引用类型。
基本数据类型:按值访问,可以操作保存在变量中的实际的值。
引用类型的值:按引用访问
4.1.1动态的属性
对于引用类型的值可以添加、修改和删除属性和方法,不能给基本类型的值添加属性(但不会报错,undefined)
4.1.2复制变量值
复制基本类型的值:在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。
复制引用类型的值:复制是一个指针,指向同一个对象。所以改变其中一个变量就会影响另一个变量。
4.1.3传递参数
ECMAScript中所有函数的参数都是按值传递:把函数外部的值复制给函数内部的参数。
传递基本类型的值:被传递的值会复制给一个局部变量(即命名参数,也就是arguments对象中的一个元素)
传递引用类型的值:把被传递的值在内存中的地址复制给一个局部变量。因此这个局部变量的变化会反映在函数的外部
提示:可以把ECMAScript函数的参数想象成局部变量
4.1.4检测类型
检查基本数据类型:typeof操作符
检测引用类型的值:instanceof操作符
4.2执行环境及作用域
执行环境:定义变量或函数有权访问的其他数据,决定了它们各自的行为。
变量对象:每个执行环境都有的一个变量对象,保存环境中定义的所有变量和函数。代码无法访问,解析器会使用。
全局执行环境:最外围的一个执行环境。在web浏览器中是window对象。
函数的执行环境:每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。
作用域链:保证对执行环境有权访问的所有变量和函数的有序访问。
作用域链的前端始终是当前环境的变量对象。(如果这个变量是函数,将它活动对象作为变量对象)(活动对象在最开始只包含arguments对象)
作用域链中下一个变量对象来自于外部环境,在下一个为下一个外部环境……
作用域链的最后一个对象始终是全局执行环境的变量对象。
标识符解析:沿这作用域链一级一级地搜索标识符的过程。从作用域链最前端开始逐级向后回溯直到找到标识符。
内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。
4.2.1延长作用域链
try-catch语句的catch块和with语句可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除。
catch语句:创建一个新的变量对象,包含被抛出的错误对象的声明。
with语句:将指定的对象添加到作用域链中。
4.2.2没有块级作用域
js中,if语句for语句中的变量声明会将变量添加到当前的执行环境中。
声明变量
使用var声明的变量会自动被添加到最接近的环境中
没使用var声明该变量会自动被添加到全局环境中
提示:1.不声明而直接初始化变量是一个常见的错误做法,在严格模式下会报错
查询标识符
搜索过程从作用域的前端开始,向上逐级查询与给定名字匹配的标识符
如果局部环境存在同名标识符,就不会使用位于父环境中的标识符
提示:1.访问局部变量要比访问全局变量快,因为不用向上搜索作用域链。js引擎优化标识符查询使这个差别可以忽略不计。
4.3垃圾收集
执行环境负责管理代码执行过程中使用的内存
原理:找出不再使用的变量释放其占用的内存
垃圾收集器会按照固定的时间间隔周期性的执行
垃圾收集器必须跟踪哪个变量有用哪个变量没用,对不再有用的变量打上标记。
标识方式:1.标记清除 2.引用计数
4.3.1标记清除
最常用
当变量进入环境时标记为“进入环境”,离开环境时标记为“离开环境”。
垃圾收集器在运行时给内存中所有变量打上标记,然后去掉环境中的变量以及被环境中的变量引用的变量的标记。这时仍有标记的变量为准备删除的变量。最后垃圾收集器完成内存清除工作,销毁带标记的值并回收内存空间。
4.3.2引用计数
不常见
跟踪记录每个值被引用的次数。
4.3.3性能问题
垃圾收集器是周期性运行。
垃圾收集例程回收的内存分配量低于15%,则变量字面量数组元素的临界值就会加倍。
提示:有的浏览器可以出发垃圾收集过程但不推荐。
4.3.4管理内存
优化内存:不用的数据设置为null来释放引用(解除引用)。局部变量会在离开执行环境时自动被解除引用。
解除一个值的引用并不意味着自动回收该值所占的内存,而是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。