变量、作用域和内存问题 context
变量
基本类型 和 引用类型 的值
- 基本类型有:Undefined, Null, Boolean, Number, String (与 java 不同,string 也是基本类型)
- 引用类型是指可能由多个值构成的对象
基本类型值和引用类型值的特点:
- 基本类型值在内存中占据固定大小的空间,因此保存在栈内存中
- 引用类型的值是对象,保存在堆内存中
- 包含引用类型的变量实际上包含的并不是对象本身,而是指向该对象的指针
- 一个变量赋值给另一个变量,如果是基本类型,会创建这个值的副本,如果是引用类型,复制的其实是指针。最终两个变量指向同一个对象。
- 引用类型可以添加属性,基本类型不可以。例如:
var a = "123";
a.age = 21;
alert(a.age);//undefined
- 函数是按值传递参数的,而非按引用传递参数。(相当于被传递的值会复制给函数的参数,基本类型和引用类型各自的复制不同)
- 检测类型
- typeof 基本类型可以有效的判别基本类型
- instanceof 来判别某个值是何种对象
执行环境及作用域
1. 执行环境(作用域)
- 执行环境分为全局环境和函数执行环境
- 每次进入新的执行环境,会创建新的作用域链
- 作用域链中,局部的环境,有权访问父级的作用域,无权访问子级作用域
- 执行环境有助于确定何时释放内存
2. 作用域链延长:
- with 语句
- try-catch 语句的 catch 块
- catch 块中,只对传进来的 e 特殊处理,在 catch 声明的变量,依然能在 catch 外部块访问到,说明他并不是单独的作用域
3. js 没有块级作用域
js 的作用域是函数级的,没有块级作用域,这点经常会导致理解上的错误。 例如:
for (var i = 0; i < 10; i++) {
doSomeThing();
}
alert(i); // 10
变量名 i 在第四行仍然可以打印出来,是因为,for 循环中,并不是独立的作用域。var i , 会被提升到 for 循环所在的函数。所以 i 仍然存在
变量名提升:使用 var 声明的变量会自动被添加到最接近的环境中,而没用 var 的,则会添加到全局环境中
垃圾回收
1. 标记清除
- 离开作用域的值自动被标记为可回收。因此在垃圾收集阶段将被回收
- 目前主流的收集算法是标记清除
2. 引用计数
- 引用计数在循环引用的时候,可能导致内存泄漏
- 应该在变量不需要用到的时候解除引用,有助于解除循环引用,并且有效的垃圾回收
3. 管理内存:为了确保占用最少的内存让页面获得更好的性能,则需要解除引用(当变量不在有用,将其置为 null);
> 注意,解除引用后,并不意味着立即被回收,只有下次垃圾收集器执行的时候,才会真正回收