javascript 基础笔记 变量、作用域、内存问题
一、变量
变量可以用来保存两种类型的值: 基本类型值和引用类型的值
1. 基本类型值具有以下特点
- 基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中。
- 一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本。
2. 引用类型的值具有以下特点
- 引用类型的值是对象,保存在堆内存中。
- 包含引用类型值得变量实际上包含的并不是引用类型本身,而是一个指向该对象的指针。
- 从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象。
3. 确定一个值的类型
- 确定一个值是哪些基本类型可以使用 typeof操作符。
- 确定一个值是哪些引用类型可以使用instanceof 操作符。
var a = 123; alert(typeof a); // number var reg = new RegExp(); alert(reg instanceof Array); // false alert(reg instanceof RegExp); // true
二、执行环境即作用域
所有的变量都存在于一个执行环境中,这个执行环境决定了变量的生命周期,以及哪一部分代码可以访问其中的变量。
每一个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中,但是这个对象只有解释器在后台处理时才会用到,我们并不能访问。
- 执行环境有全局执行环境和函数执行环境之分
全局环境是最外层的一个执行环境,在Web浏览器中全局环境被认为是window对象。
某个执行环境中所有的代码执行完毕后,该环境被销毁,保存在其中的所有的变量和函数都会被销毁。
全局环境执行到应用程序退出时才会被销毁。例如关闭浏览器
- 执行流的控制机制:
每个函数都有自己的执行环境,当执行流进入一个函数时。函数的环境就会被推入一个环境栈中,而函数执行完之后,栈将其环境弹出,把控制权返回给执行之前的控制函数。
- 作用域链:
当代码在一个执行环境中执行时,会创建用于搜索变量和函数的一个作用域链。作用域链的前端始终是当前代码所在环境的变量。
函数的局部环境不仅有权访问当前函数作用域中的变量,而且有权访问其他父环境,乃至全局环境的变量。而全局环境只能访问,全局环境的变量。即,在某个环境中可以访问当前环境以及父环境的变量而不能访问子环境的变量
- 标识符的查询:
搜索标识符的过程从作用域链的前段开始,向上逐级查询与给定名字相等的标识符,找到了搜索过程就停止。如果没有找到则继续搜索一直找到全局环境变量。如果全局环境中也没有这个标识符则意味着,这个标识符还未声明。
三、内存------javascript中的垃圾回收
- 标记清除的垃圾回收机制:
标记清除是目前主流的算法,这种算法的思想是给当前不使用的值加上标记,然后回收其内存。
离开作用的值将被自动标记为可以回收,因此将在垃圾收集期间被删除。
- 引用计数的垃圾回收机制:
这种算法的思想是追踪记录所有值被引用的次数。当前javascript引擎都不再使用这种机制,但是在IE中访问原生的DOM元素时,这种算法仍然会导致问题。
- 当代码中出现循环引用时,引用计数机制就会出现问题。例如
var element = document.getElementById('name'); var myObject = new Object(); myObject.elem = element; element.obj = myObject;
上面代码中myObject首先包含了element 然后element有包含了 myObject 这样就造成了一个循环引用在这种情况下如果使用的是引用计数的垃圾回收机制就会使得这两个对象的内存永远得不到释放。
- 解除变量的引引用
优化内存占用的最佳方式:执行中的代码只保存必要的数据。
一旦数据不在有用,最好将其值设置为null 来释放期引用。--------------------------------这就是解除变量的引用
解除引用的作用: 让值脱离执行环境,以便垃圾回收机制将其回收。