-------------------------------------------
闭包的应用场景
1.使用闭包代替全局变量
2.函数外或在其他函数中访问某一函数内部的参数
3.在函数执行之前为要执行的函数提供具体参数
4.在函数执行之前为函数提供只有在函数执行或引用时才能知道的具体参数
5.为节点循环绑定click事件,在事件函数中使用当次循环的值或节点,而不是最后一次循环的值或节点
6.暂停执行7.包装相关功能
4.在函数执行之前为函数提供只有在函数执行或引用时才能知道的具体参数
// 动态绑定a集合的注册点击事件,在事件处理函数test1中提供参数-该点击事件的a元素本身。 var aa = " ha! " function test(obj){ return function (){alert(obj);}} var nodes = document.getElementsByTagName( " a " ); for ( var i = 0 ;i < nodes.length;i ++ ){ var test1 = test(aa); // 由于是提前提供参数,只能提供已知的具体参数,无法事先得知点击事件的a元素本身。 // 这里想提供点击事件的a元素本身作为参数宣告失败! nodes[i].onclick = test1; // 只有在注册点击事件时,才会知道该点击事件的a元素是哪个 }
// 以下是解决方式 function associateObjWithEvent(obj,methodName){ return ( function (e){ e = e || window.event; return obj[methodName](e, this ); //重点看这里! 有两个参数, //e:event,元素绑定事件时,绑定的是对内部函数的引用,故在触发事件时,执行的是内部函数。
//内部函数有个e参数,刚好在事件触发时,能捕获到是什么事件类型。
//this:这里需要的就是this参数,以便当元素触发事件处理函数执行时,this=触发事件的元素本身
//this参数无法从外部传入进来。传入进来的this都会被转化特定对象
); } function DhtmlObject(elId){ var el=document.getElementById(elId); if(el){ //el.οnclick=associateObjWithEvent(this,"doOnClick"); el.onmouseover=associateObjWithEvent(this,"doMouseOver"); el.onmouseout=associateObjWithEvent(this,"doMouseOut"); } } DhtmlObject.prototype.doMouseOver=function(event,element){ alert(event);//第一个参数,只在事件执行时,才知道是什么事件,这里是MouseEvent alert(arguments[0]);//第一参数, alert(element);//第二个参数,只在事件执行时,才知道是指代触发事件的元素本身 alert(arguments[1]);//第二个参数 } var hello=new DhtmlObject("hello"); //执行
另一个例子
function associateObjWithEvent(obj,methodName){ return ( function (e){ e = e || window.event; return obj[methodName](e); });} function DragListener(){ this .down = function (){ alert( this ) alert(arguments[ 0 ]) }, this .move = function (){ alert( 2 ) }} var obj = new DragListener();document.getElementById( " hello " ).onmousedown = obj.down; // 正确 但我们在方法中用this访问到的对象是 dom document.getElementById( " hello " ).onmousemove = obj.move; // 正确 document.getElementById( " hello " ).onmousedown = associateObjWithEvent(obj, ' down ' ); // 正确 document.getElementById( " hello " ).onmousemove = associateObjWithEvent(obj, ' move ' ); // 正确
改进的例子,无限参数
function associateObjWithEvent(obj, methodName){ slice = Array.prototype.slice; var args = slice.call(arguments, 2 ); // 从第三个参数开始赋值 return ( function (e){ e = e || window.event; var array = slice.call(arguments, 0 ); array.push(e); // 第一个参数为event return obj[methodName].apply( this ,array.concat(args)); // 第二个参数,依次... });} function DhtmlObject(elementId){ var el = document.getElementById(elementId); if (el){ // el.onclick = associateObjWithEvent(this, "doOnClick"); el.onmouseover = associateObjWithEvent( this , " doMouseOver " , " hello2 " , " aaa " ,event); // 第一个参数为event,hello2是第二个参数, // 因为event只有在事件处理函数执行时才会知道是具体什么事件类型,无法通过传参提供,传参的event只能识别为null
}}DhtmlObject.prototype.doMouseOver = function (event){ // doMouseOver 方法体。 alert( " this: " + this .id); // this:hello alert( " arg0: " + arguments[ 0 ]) ; // arg0:MouseEvent alert( " arg1: " + arguments[ 1 ]); // arg1:hello2 alert( " arg2: " + arguments[ 2 ]); // arg2:aaa alert( " arg3-event: " + arguments[ 3 ]); // arg3-event:null alert( " event: " + event); // event:MouseEvent } // DhtmlObject("hello"); 这样写,反而出错。因为是类的写法,必须实例化才会执行。 var hello = new DhtmlObject( " hello " )