概念:闭包就是能够读取其他函数内部变量的函数。
作用:一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
闭包注意问题:
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
作用域链
概念:在一个函数中嵌套多个函数,并且各自定义的相同的变量名,当函数访问变量时,就形成了作用域链。
查找顺序:从当前函数开始查找,如果没有找到,向上一级函数开始查找,直到找到为止,如果一直没有找到,则说明该变量未定义。
作用域链明确表示:在变量解析过程中首先查找局部作用域,然后查找上层作用域。
垃圾回收
有两种策略来实现垃圾回收:
标记清除 和 引用计数;
标记清除:垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记,然后,它会去掉环境中的变量的标记和被环境中的变量引用的变量的标记,此后,如果变量再被标记则表示此变量准备被删除。 2008年为止,IE,Firefox,opera,chrome,Safari的javascript都用使用了该方式;
引用计数:跟踪记录每个值被引用的次数,当声明一个变量并将一个引用类型的值赋给该变量时,这个值的引用次数就是1,如果这个值再被赋值给另一个变量,则引用次数加1。相反,如果一个变量脱离了该值的引用,则该值引用次数减1,当次数为0时,就会等待垃圾收集器的回收。
函数嵌套
一个函数定义的内部可以定义其他的函数。
函数自执行
(function (argument1,argument2){
这里是要执行的代码
})();
将函数声明用()括起来,相当于一个函数表达式。
创建调用函数注意问题
如果两个函数的命名相同,后面的将会覆盖前面的函数。 以基本语法声明的函数,会在页面载入的时候提前解析到内存中,以便调用。所以可以在函数的前面调用。但是以字面量形式命名的函数,会在执行到他的时候,才进行赋值。所以只能在函数的后面调用。
在不同的<script></script>块中,因为浏览器解析的时候是分块解析的,所以前面的块不能调用后面块的函数,所以在不同的块之间调用函数的时候,应该先定义后调用。
带有参数的函数
参数的作用:
可以动态的改变函数体内对应的变量的值,使同一函数体得到不同的结果。
形参:在定义函数的时候,函数括号中定义的变量叫做形参。用来接受实参的。
实参:调用函数的时候,在括号中传入的变量或值叫做实参。用于传递给形参。
参数详解
参数的类型
– 可以是任何的数据类型。
参数的个数
– 实参和形参数量相等,一一对应。
– 实参小于形参,不会报错,多出形参的值会自动赋值为undefined。
– 实参大于形参,不会报错,但如果要获得多出实参的值,需要用arguments对象来获取。
arguments对象详解
每创建一个函数,该函数就会隐式创建一个arguments对象,他包含有实际传入参数的信息。
arguments对象的属性
– length 获得实参的个数
– callee 获得函数本身的引用
– 访问传入参数的具体的值。arguments[下标]
Var a =100 function test() { alert(a); a = 10; alert(a); } test(); alert(a); 阅读以上代码,结果应为多少?
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <body> <script> //概念:闭包就是能够读取其他函数内部变量的函数。 //闭包可以让局部变量持久化 //作用:一个是前面提到的可以读取函数内部的变量, //另一个就是让这些变量的值始终保持在内存中 //【注意】1、在退出函数之前,将不使用的局部变量全部删除 //2、闭包会在父函数外部,改变父函数内部变量的值。 //3、不要随便改变父函数内部变量的值 //4、函数在调用时会开辟新空间,这块内存空间在函数执行完毕时释放 //createComparisonFunction() 作用域 function createComparisonFunction(propertyName){ return function(object1,object2){ //内部函数 访问了propertyName var value1 = object1(propertyName); var value2 = object2(propertyName); if(value1 < value2){ return -1; }else if(value1 > value2){ return 1; }else{ return 0; } }; } function compare(value1,value2){ if(value1 < value2){ return -1; }else if(value1 > value2){ return 1; }else{ return 0; } } var result = compare(5,10); </script> </body> </html>
用闭包打印li的下标
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <ul> <li>蜡笔小新</li> <li>野原葵</li> <li>野原美伢</li> <li>野原广志</li> </ul> <script> // var li = document.getElementsByClassName("li"); // for(var i = 0;i<li.length;i ++){ // function dianji(){ // var j = i; // function a(){ // alert("下标为"+j); // } // return a; // } // li[i].onclick = dianji() // } //第二种方法 var li = document.getElementsByTagName("li"); for(var i = 0;i<li.length;i ++){ li[i].onclick = function(num){ return function(){ alert(num); } }(i);//执行匿名函数 } </script> </body> </html>