js学习笔记--变量、作用域和垃圾回收机制

数据类型

js变量是在特定时间用于保存特定值的一个名字,是松散类型的,变量的值和类型在脚本的生命周期内可以改变。

ECMAScript 变量包含两种不同数据类型的值:
1、基本类型值: Undefined, Null, Boolean, Number, String 这些简单数据段,占据大小固定的空间,保存在栈内存中(按值访问)。
2、引用类型值: 由多个值构成的对象,大小不固定,被保存在堆内存里,并在栈内存中存放该对象访问地址,或者说是指针(按引用访问)。

js不允许直接访问内存中的位置,所以不能直接操作对象的内存空间,而是操作对象的引用,并非实际的对象。

复制变量时发生了啥

从一个变量向另一个变量复制基本类型值时,会在变量对象上创建一个新值,然后把该值复制到为这个新变量分配的位置上,这两个变量互不影响,相互独立。

从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中,只不多,这个值的副本实际上是一个指针,所以改变一个变量会影响另一个。

注意事项:

ECMAScript 中所有函数的参数都是按值传递的,也就是说,将函数外部的值复制给函数内部的参数,如果是基本类型值,就是相互独立的,如果是引用类型值的传递,就会出现函数内部的局部变量的变化会反映在函数的外部,以为按值传递时传递了指针,而实际对象所处的堆内存是全局的。

function setName(obj) {
    obj.name = "Nicholas";
    obj = new Object();
    obj.name = "Greg";
}
var person = new Object();
setName(person);
console.log(person.name); //"Nicholas"

作用域

1、所有变量(包括基本类型和引用类型)都存在于一个执行环境(也称为作用域)当中,这个执行环境决定了变量的生命周期,以及哪一部分代码可以访问其中的变量,有助于确定应该何时释放内存。

2、执行环境分全局执行环境和函数执行环境,每当进入一个新执行环境,都会创建一个用于搜索变量和函数的作用域链。函数的局部环境不仅有权访问函数作用域中的变量,而且有权访问其包含(父)环境,乃至全局环境。

延长作用域链的两种情况:
1、try-catch 语句的 catch 块(会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明);
2、width 语句(将指定的对象添加到作用域链中);

这两个语句都会在作用域链的前端添加一个变量对象,该变量对象会在代码执行后被移除。

回收机制

JavaScript 是一门具有自动垃圾收集机制的编程语言,开发人员不必关心内存分配和回收问题。离开作用域的值将被自动标记为可以回收,因此将在垃圾收集期间被删除。

垃圾收集算法主要有两种:
1、标记清除 —— 是目前主流的垃圾收集算法,这种算法的思想是给当前不使用的值加上标记,然后再回收其内存;
2、引用计数 —— 这种算法的思想是跟踪记录所有值被引用的次数。JavaScript引擎目前都不再使用这种算法;

但在 IE 中访问非原生 JavaScript 对象(如 DOM 元素)时,这种算法可能会出现因循环引用导致的问题。(IE9以后因为DOM已经改为js对象将不再出现这种问题)

注意事项

一旦数据不再有用,最好通过将其值设置为 null 来释放其引用——这个 做法叫做解除引用(dereferencing)。这一做法适用于大多数全局变量和全局对象的属性。

局部变量会在它们离开执行环境时自动被解除引用。同时,为了确保有效地回收内存,应该及时解除不再使用的全局对象、全局对象属性以及循环引用变量的引用。

注意:解除一个值的引用并不意味着自动回收该值所占用的内存。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。

Tips

 1. 检测基本数据类型:用 typeof, 注意 null 也返回 object
 2. 检测一个引用类型的值是什么类型的对象:用 instanceof (用 instanceof 来检测基本类型的值,始终返回 false),来两斤栗子:
     null instanceof Object  //false
     x instanceof Object; 
     x instanceof Array;
     x instanceof RegExp; 

你可能感兴趣的:(javascript)