一、写在前面
最近研究了创建 Android 虚拟机、vscode 结合 weex 开发 Android APP、Vmware 装 MAC 虚拟机的事,看的内容不够多,接下来加油
二、变量、作用域和内存问题
2.1 基本类型、引用类型
-
变量类型:
- 基本类型:简单数据段,按值访问的,可操作变量中的实际值
- 引用类型:对象,按引用访问,操作对象的引用,能动态添加属性
-
变量复制:
- 基本类型:直接分配两个内存空间,互不影响
- 引用类型:复制了指针,指向堆中同一对象,相互影响
-
传参(见示例):
- 基本类型传值,互不影响
- 引用类型传地址,相互影响
// 示例
function setName(obj) {
// 指向 person,添加属性 name
obj.name = "Nicholas";
// 指针指向新的内存空间
obj = new Object();
obj.name = "Greg";
// 函数执行完毕后,局部对象立即销毁
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
-
检测类型
- typeOf 特殊:null 返回 object
- instanceof:引用类型检测,(某实例)instanceof(某类型)
2.2 执行环境、作用域
-
执行环境:定义变量或函数有权访问的其他数据范围,决定行为。中有变量对象,保存环境中定义的所有变量和函数,环境销毁,变量、函数销毁
- 全局执行环境,web 中为 window 对象
- 局部执行环境,执行流进入函数,函数环境被推入环境栈,执行后,栈将其环境弹出,控制权返回之前的执行环境
- 作用域链:在环境中执行代码,会创建变量对象的作用域链,保证(有权访问当前环境的)变量和对象有序访问
作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象(activation
object)作为变量对象。活动对象在最开始时只包含一个变量,即 arguments 对象(这个对象在全局环境中是不存在的)。作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象
- 标识符解析:沿作用域链一级一级搜索标识符。从作用域链前端开始,逐级向后,直到找到标识符为止
-
内外关系:
- 内部环境可以通过作用域链访问所有外部环境,外部环境不能访问内部环境中的任何变量或函数
- 每个环境可以向上级搜素,但不能向下搜索进入另一个执行环境
2.3 延长作用域链
在作用域链前端加临时变量对象,执行后移除
- try-catch 中 catch
- with
function aaa( ) {
var qs = '?id=12';
// 引用 location,with 内部可用 location 的所有属性和方法
with(location) {
// href 为 locaiton.href
var url = href + qs;
}
// 在 aaa()内可拿到 with()内定义的 url
return url;
}
- catch 特殊情况:IE8 以前 catch 的错误对象会添加至执行环境的变量对象,catch 外也能访问(IE9 修复了)
2.4 没有块级作用域
{} 封闭的代码块中定义的变量,执行后没有被销毁,依旧存在于 {} 外部执行环境中
-
声明变量
- var:自动添加到最接近的环境中。没有 var 直接声明,添加到全局环境中(严格模式下导致错误,不推荐)
-
查询标识符
- 从作用域链前端开始,向上逐级查询,直至匹配为止(先自身再向上)
- 访问局部变量比访问全局变量更快
2.5 垃圾收集
执行环境管理着代码执行过程中使用的内存
自动垃圾收集机制:实现所需内存分配、无用内存回收,自动管理。固定时间间隔,周期性检索不再继续使用的变量,打标记,释放其占用的内存
-
回收策略
-
标记清除(主流)
- 变量进入环境、离开环境,标记不同
- 标记方式:翻转某位,或以环境列表、离开环境列表区分,或其他
- 运行机制:内存中全部变量加标记,再去掉环境中的、被环境中引用的变量的标记,剩下还有标记的,准备删除,垃圾收集器清除内存,销毁值,回收空间
-
引用计数(不常见)
- 跟踪每个值被引用的次数
- 计数规则:引用类型的值赋给一个变量,引用次数加一;已经引用的变量不再引用它,引用次数减一
- 运行机制:垃圾收集器运行,释放引用次数为 0 的值所占的内存。
-
特殊情况:
- 循环引用(例:两对象间相互引用,则引用次数永不为 0,无法销毁)
- IE9 之前,BOM、DOM 对象以 COM(使用引用计数策略)形式实现,循环引用后删除 DOM,对应值也不会回收(通过赋值 null,手动断开循环引用解决)。IE9 后,BOM、DOM 转为真正的 js 对象,避免了该问题
-
-
性能问题
- IE7 之前:内存分配量达到任一临界值(256 变量、4096 对象数组、64K 字符串)则回收,缺点:如一直在临界值之上,则一直回收
- IE7 修正:临界值动态修正,初始与之前相等,回收的分配量低于 15%,临界值加倍,回收的内存分配量 85%,临界值恢复初始
- 手动触发方式(不推荐):
// 手动触发方式
// IE
window.CollectGarbage();
// Opear7~
window.opera.collect();
-
管理内存
- 内存分配:给 web 浏览器的少于给桌面应用的,防止系统崩溃
- 优化内存占用:只保存必要数据,不用的置 null(解除引用,给全局中的用,局部的会自动销毁),等待下一次垃圾回收