1.匿名函数
定义:没有名字的函数,可以配合其他语法使用也可以单独使用。
function fn1(){} //函数声明 var fn1=function(){} //函数表达式 function(){} //匿名函数 匿名函数配合其他语句执行--dom添加事件 匿名函数自执行---(function(){})() 匿名函数自执行实现模仿块级作用域 var obj=(function(a,b){ var c=3; function _add(){
return a+b;
}function addMore(){ return _add()*c } return {getRes:addMore} })(100,200); console.log(obj.getRes()) //900
模范块级作用域的方法:
- 通过一个变量来接收匿名函数自执行的结果。
- 访问匿名函数返回的允许呗外部使用的变量和方法。
2.闭包
定义:一个可以访问另一个函数内部变量的函数。
使用场景:
//函数作为返回值--形成闭包 function fn1(c){ var a=100; return function(){ var b=200; console.log(a+b+c) } } fn1(300)() //600 //函数作为参数--形成闭包 (function(fn){ var d=400; fn(d)() })(fn1) //700
var a=100;
function fn1(){
var a=200;
function fn2(){
//var a=500
var b=300;
console.log(a+b)
}
return fn2
}
(function(fn){
var a=400;
fn()()
})(fn1) //500
缺点:增加内存开销
优点:加快有些变量的访问速度(因为它允许将函数与其所操作的外部环境数据关联起来,这种关联关系有利于变量的持久化缓存)
3.内存泄漏与垃圾回收机制
内存泄漏:
- 并不是说内存开销的增加就是内存泄漏,如果内存开销是可控的,可以手动清理的,这就不能算是内存泄漏。
- js中闭包中对于外层函数的值类型的引用基本不会造成内存泄漏。
- 能够造成内存泄漏的情况,一般是闭包中引用了外层函数的引用类型导致的,同时外层函数的引用类型的变量还必须是数据量较大,容易快速增量变化的引用类型的变量(对象 数组 定时器实例对象 绘图实例对象 第三方依赖库的实力对象)
垃圾回收机制:
- js本身具有自动垃圾回收机制(找出不再继续被使用的变量,然后释放其占用的内存)
- 在函数被调用形成的执行环境中,这个执行环境会负责管理代码执行过程中使用的内存,这个过程是js自动进行的,每个变量所使用和分配的内存空间全部自动管理,同事当他们不再被使用的时候,也会被自动回收
- 垃圾回收器会按照一定的时间间隔周期性的执行垃圾回收机制。
- 那些变量需要被清除释放,js中有2种确认方式,一种标记清除,一种引用清除。
标记清除:垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记,当变量进入执行环境时,将其标记为‘进入环境’,而当变量离开执行环境时,则将其标为‘离开环境’。在垃圾回收器检测的时候,她或去掉环境中变量以及被环境中的变量引用的变量标记, 之后 垃圾收集器就开始内存清除工作,销毁带标记的值,并收回其占用的内存空间。
引用清除:就是记录一个变量引用的次数,当这个值的引用次数变成0时,说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来,这样,当垃圾回收器下次再运行时,它就会释放那些引用次数为0的值所占用的内存。
4.避免使用闭包造成内存泄漏的简单方法
- 避免在闭包中引用外层函数中数据量较大,容易快速增量变化的变量。
- 在闭包中尽量避免与定时器相互嵌套使用,如果有在一起使用的情况,一定要对使用过的定时器进行清除
- 对闭包中引用的外层函数的变量进行手动解除引用,解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。
function fn1(){ var a={ x:100, y:200, } return function(){ console.log(a.x+a.y) } a=null; //手动解除引用 } fn1()() //300