闭包是指有权访问另一个函数作用域中的变量的函数,并且在闭包内部形成一个外部无法访问的局部作用域。创建闭包的常见方式是在一个函数内部创建另一个函数。程序代码如下所示:
var oDivs = document.getElementsByTagName('div'); for (var i = 0; i < oDivs.length; i++) {; (function(num) { oDivs[num].onclick = function() { alert('我是第' + (num + 1) + '个DIV'); } })(i); //i为实参 //alert(num);//导致错误! }
知识点:
(1)代码中:
; (function(num) { oDivs[num].onclick = function() { alert('我是第' + (num + 1) + '个DIV'); } })(i);
等同于:
var fn = function(num) { oDivs[num].onclick = function() { alert('我是第' + (num + 1) + '个DIV'); } } fn();
分号为了使语句更严格,防止出现歧义。
(2)
//alert(num);//导致错误!
此行调用num由于不在同一作用域,会导致错误!
(3)参数i的传递非引用类型,是按值类型传递。
优点:加强封装性,可以达到对变量的保护作用。
缺点:
1)由于闭包内部变量优先级高于外部变量,所以多查找作用域链中的一个层次,就会在一定程度上影响查找速度。
2)内存浪费,程序代码如下:
function teachersInfo(propertyName){ return function(obj1,obj2){ return obj1[propertyName]+'-'+obj2[propertyName] } } //创建函数 var getTeachers=teachersInfo('name'); //调用函数 var result=getTeachers=getTeachers({name:'耿教师'},{name:'陈教师'}); //接触对匿名函数的引用(以便释放内在) alert(result); getTechers=null;
知识点:
当执行函数teachersInfo时,函数的作用域链包括活动对象(参数propertyName)和全局变量对象,当函数teachersInfo执行完毕后,其活动对象也不会被销毁,因为匿名函数的作用域链仍然在引用这个活动对象。
getTeachers指向的是匿名函数的地址,所以需要释放这个句柄
getTechers = null;