第四章:变量、作用域和内存问题
-
基本类型和引用类型的值
ECMAScript 变量可能包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值指的是 简单的数据段,而引用类型值指那些可能由多个值构成的对象。
JavaScript不允许直接访问内存中的位置, 也就是操作对象的时候只是操作的引用而不是实际的对象。
-
动态的属性
-
引用类型的值,我们可以为其添加属 性和方法,也可以改变和删除其属性和方法。
-
不能给基本类型的值添加属性
-
-
复制变量值
-
一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制 到为新变量分配的位置上
-
一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到 为新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一 个对象。复制操作结束后,两个变量实际上将引用同一个对象。
-
传递参数
- ECMAScript 中所有函数的参数都是按值传递的(跟Java有点像)
-
检测类型
-
typeof 操作符:用与对象返回的是一个object要想知道是什么类型的可以用 instanceof 给定引用类型(根据它的原型链来识别;第 6 章将介绍原型链)的实例,那么 instanceof 操作符就会返回 true。
alert(person instanceof Object); // 变量 person 是 Object 吗?
-
-
执行环境及作用域
执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个 与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中.(感觉就是栈或者是一个函数的包裹的一个范围)
-
作用域链
保证对执行环境有权访问的所有变量和函数的有序访问
作用域链的前端,始终都是当前执行的代码所 在环境的变量对象
如果这个环境是函数,则将其活动对象(activation object)作为变量对象
全局执行环境的变量对象始终都是作用域链中的最后一个对象。
-
-
延长作用域链
- try-catch 语句的 catch 块;with 语句。(这两个语句都会在作用域链的前端添加一个变量对象)
-
没有块级作用域
-
声明变量
用 var 声明的变量会自动被添加到最接近的环境
-
查询标识符
搜索过程从作用域链的前端开始,向上逐级查询与给定名字匹配的标识符。如果在局部环境中找到 了该标识符,搜索过程停止,变量就绪。如果在局部环境中没有找到该变量名,则继续沿作用域链向上 搜索。(从这一级向外)
-
-
-
垃圾收集
-
原理:找出那些不再继续使用的变 量,然后释放其占用的内存。(会按照固定的时间间隔(或代码执行中预定的收集时间), 周期性地执行这一操作)
-
标记清除
进入环境一个标记,推出环境一个标记,
-
引用计数
声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是 1。 如果同一个值又被赋给另一个变量,则该值的引用次数加 1。相反,如果包含对这个值引用的变量又取 得了另外一个值,则这个值的引用次数减 1。当这个值的引用次数变成 0时,则说明没有办法再访问这 个值了,因而就可以将其占用的内存空间回收回来
-
性能问题
如果 垃圾收集例程回收的内存分配量低于 15%,则变量、字面量和(或)数组元素的临界值就会加倍。如果 例程回收了 85%的内存分配量,则将各种临界值重置回默认值。
-
管理内存
一旦数据不再有用,最好通过将其值设置为 null 来释放其引用——这个 做法叫做解除引用(dereferencing)。这一做法适用于大多数全局变量和全局对象的属性。
-
-
小结
JavaScript的基本类型都有相同的内存空间,关于复制的问题
如果是基本类型则复制副本,引用则复制引用,新旧两个指向同一个对象。参数传递类似与Java的只有值传递,关于执行环境,感觉说不明白但是好像又懂。垃圾处理的话,注意不用的就设置null来释放空间。