Js 是一门完整的面向对象语言,同时也有 函数式语言特性。其中 就有 闭包和高级函数。
听到 闭包,你会想到什么?
闭包是什么?
闭包的作用是什么?
为什么要用闭包,它为我解决 什么问题?
1. 它是js一种语言特性,它 跟 变量的作用域和垃圾 回收机制相关
2 . 能够读取其它函数 内部变量的函数 称为闭包;
3. 在外部读取引用函数内部变量,外部
闭包
它是一个很难又必须征服的概念。它的形成 与变量的作用域 以及生存周期密切相关。
1. 变量的作用域
变量的作用域 指的是变量的有效范围。
在函数中声明一个变量的时候:①没有关键字 var ,这个变量就会变成 全局变量。
②有关键字 var,就是 局部变量。只有在函数内部才能访问这个 变量,函数外部 访问不到。
var func = function ( ) {
var a =1; // 局部变量
alert ( a ) ;
}
func ( ) // 1
alert ( a ) // a is not defined
var func = function ( ) {
a = 1 ; // 全局变量
alert( a ) ;
}
func( ); // 1
alert( a ) // 1
在JS中,函数可用来创造函数作用域。此时的函数像一层半透明的玻璃,在函数里面可以看到外面的变量。而在函数外面却看不到函数里的变量。
这是因为,在函数中搜素一个变量的时候,如果该函数内并没有声明这个变量,那么此次的搜索过程 会随着代码的执行环境创建的作用域链 往外逐层搜索,直到全局对象为止。
变量的搜索是从内到外 而非从外到内。
var a = 1 ;
var func1 = function ( ) {
var b = 2 ;
var func2 = function ( ) {
var c = 3 ;
alert ( b) ; // 2
alert ( a ); //1
}
func2( );
alert( c ); // c is not defined;
}
func1 ( );
2.变量的生命周期
提到生命周期,不得不提 JS 具有的自动垃圾收集机制。
简单来说,就是 销毁掉环境中无用的变量,完成内存清理工作,从而回收它们所占用的空间。
具体来说1:执行环境会负责管理代码执行工程中使用的内存。在编写JS时,开发人员不用再关心内存的使用问题,所需内存的分配以及无用内存的回收完全实现了自动管理。原理很简单:找出那些不再继续使用的变量,然后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔周期性执行这一操作。
具体来说2: 局部变量只在函数执行的过程中存在。而在这个过程中,会为局部变量在堆或栈内存上分配相应的空间,以便存储它们的值。然后在函数中使用这些变量,直至函数执行 结束。此时,局部变量就没有存在的必要了,因此释放掉它们的内存以供将来使用。
对于全局变量来说,它的生命周期当然是永久的。对于函数内部 的局部变量来说,当退出函数时,这些变量即失去了它们的价值,它们都会随着函数调用的结束而被摧毁。
var func1 = function ( ) {
var a = 1 ;
a++ ;
alert( a ) ;
}
func1 ( ) ; // 2;
func1 ( ) ; // 2;
func1 ( ) ; // 2;
var func2 = function ( ) {
var a = 1 ;
return function ( ) {
a++;
alert( a );
}
}var f = func2 ();
f ( ) ; // 2
f ( ) ; // 3
f ( ) ; // 4
执行函数func1时,每次执行都 弹 2。说明每次执行,a重新被赋值 1; 即每次调用函数结束后, 变量 a 在堆或栈里存的值被销毁(赋值null)。
执行函数func2时,数字依次增加。说明局部变量a并没有在函数执行后被销毁。 而是存活在某个地方。这是因为当执行 var f = func2( ) 时,f 返回了一个匿名函数的引用,这个引用可以访问到 func2 () 被调用时产生的环境,而局部变量 a 一直处在这个环境里。既然 局部变量还能被外界访问,这个局部变量就有了不被销毁的理由。
var nodes = document.getElementsByTagName('div');
for(var i = 0; i < nodes.length; i++) {
nodes[i].onclick = function () {
alert( i )
}
}
无论点击哪个div ,最后弹的都是 5.这是因为 onclick 是异步触发的,当点击某个div时,会顺着作用域链由内向外查找变量 i 值。 而for循环早已结束,每次找到的都是 5。
解决方法是 在闭包的帮助下,把每次循环的 i 值都封闭起来。当在事件函数中顺着作用域链查找变量 i 时,会先找到封闭在闭包环境中的 i .
for(var i = 0; i < nodes.length; i++) {
(function(i){
nodes[i].onclick = function () {
alert( i )
}
})(i)
}
网友评论