javascript高程笔记-------第四章 变量作用域和内存问题
Posted 迷~途
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript高程笔记-------第四章 变量作用域和内存问题相关的知识,希望对你有一定的参考价值。
首先javascript中的变量分为基本类型和引用类型。
基本类型就是保存在栈内存中的简单数据段,而引用类型指的是那些保存在堆内存中的对象。
1.参数传递
javascript中所有参数的传递都是值传递。
1.1 基本数据类型的传递(undefined ,Null,Boolean,number,String)
1--->var money = 10;
2--->var t=function (money){
money = 5;
alert(money); //5
}
3--->t(money);
4--->alert(money); //10
执行过程 ①全局环境中初始化money的值 为10 ; ②创建函数 t 的执行环境 ;③ 执行 t 函数 复制全局环境中money的变量的值 赋值给 t 函数中的money 函数体内的money被改变 为5 然后再执行④ 全局中的money值依然为10
1.2 对象的传递 (传递是对象的引用地址)
1--->var person = new Object();
2--->var student = person;
3--->student.name = "zhangsan";
4--->alert(person.name); // zhangsan
执行过程 ①全局环境中初始化person ,person引用了栈区的一个空对象 ; ②将person引用的对象地址值复制一份 赋值给student ;③ 将student引用的对象中添加name属性 赋值为 zhangsan ④ 由于student和person引用的是同一个对象 所以值为 zhangsan!
示例图
1.1 作用域链
在浏览器中顶层的容器为window对象, 执行某段js函数时,函数内部使用的对象,首先在函数内部寻找,未找到则向上延伸至函数体外部查找,直到找到要使用的对象;
1.2 没有块级作用域
javascript 中的 if 和 for循环 内部定义的变量 将会扩充至作用域链的上一层 变量
示例 : for循环内部定义的b和i 在aa函数中 依然可以被访问到
function aa(){ for(var i=0; i<5;i++){ var b = i; } alert(i) ; //5 alert(b); //4 }
1.3 变量、查询标识符
声明方式: ①使用var 关键字 此时变量的作用范围默认在当前执行环境内部 ② 不使用var 那么这个变量将存在余全局windon对象当中
当某个函数 引用一个变量时 ,必须通过搜索来确定引用变量的值,搜索过程从当前的执行环境逐步向上寻找整个作用域链 ,找到了该变量的定义则使用已定义的值,如未找到则认为该变量的值为undefined ,
var b = 5; function a(){ alert(b); //5 }
当 执行环境内部与作用域链中 存在同名变量时候 则使用离执行环境最近的值
var b = 5; function a(){ var b=10; alert(b); //10 }
1.4 垃圾回收
javascript具有自动收集垃圾机制,但不同的浏览器有不同的实现方式
① 标记清除(mark-and-sweep),当变量进入执行环境(函数体内声明一个变量) 就将这个变量标记“进入环境”,而当变量离开环境时(0函数体执行完毕)标记“离开环境” ,大部分浏览器都是使用此方式进行垃圾回收 (截至2008年,IE,Firefox,Opera,Chrome,Safari)或类似回收策略,回收时间的周期不同而已
②引用计数 (reference counting): 当声明一个变量a ,将这个变量a赋值给另外一个变量b时 变量a被引用次数+1,当又将a的值赋给其他变量c时 ,a被引用的次数再+1,当程序继续执行 变量c的值 引用其他值时 ,则变量a的引用次数-1,再然后 变量b的值也不等于变量a时 ,变量a被引用的次数再-1
当引用次数为0时,说明不会再有任何执行环境需要变量a,因此就可以回收其占用的内存,
引用计数带来的问题---------当存在互相引用时(循环引用),将无法回收被占用的内存,导致内存泄漏
function a(){ var element = document.getElementById("somthingElement"); var myObject = new Object(); myObject.element = element; element.someObject = myObject; }
此时 a() 函数执行完毕后 element 与myObject互相引用 两者的引用次数都为1 因此无法释放其占用的内存 ,
不管浏览器采用如何的垃圾回收策略,程序内部最好的解决方式仍然是手动解除对象的引用:
function a(){ var element = document.getElementById("somthingElement"); var myObject = new Object(); myObject.element = element; element.someObject = myObject; //coding..... myObject.element = null; element.myObject = null; }
在IE9中采用了纯JavaScript对象方式实现BOM和DOM ,避免了循环引用带来的内存泄漏!
性能优化: 最佳方式就是在执行的代码中只保存有效数据,一旦确定数据不在使用,通过设置为null的方式进行解除引用
以上是关于javascript高程笔记-------第四章 变量作用域和内存问题的主要内容,如果未能解决你的问题,请参考以下文章