变量、作用域和内存问题 context

变量

基本类型 和 引用类型 的值

  • 基本类型有:Undefined, Null, Boolean, Number, String (与 java 不同,string 也是基本类型)
  • 引用类型是指可能由多个值构成的对象

基本类型值和引用类型值的特点:

  • 基本类型值在内存中占据固定大小的空间,因此保存在栈内存中
  • 引用类型的值是对象,保存在堆内存中
  • 包含引用类型的变量实际上包含的并不是对象本身,而是指向该对象的指针
  • 一个变量赋值给另一个变量,如果是基本类型,会创建这个值的副本,如果是引用类型,复制的其实是指针。最终两个变量指向同一个对象。
  1. 引用类型可以添加属性,基本类型不可以。例如:
var a = "123";
a.age = 21;
alert(a.age);//undefined
  1. 函数是按值传递参数的,而非按引用传递参数。(相当于被传递的值会复制给函数的参数,基本类型和引用类型各自的复制不同)
  2. 检测类型
  • 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);

> 注意,解除引用后,并不意味着立即被回收,只有下次垃圾收集器执行的时候,才会真正回收
上次更新: 11/25/2018, 4:13:43 PM