1 事件庫的復習及最終版封裝
- 依賴的庫:不依賴任何庫;
- 使用方法:
- 為全局函數調用;
- 系統行為事件綁定:on(ele,type,fn);解除綁定:off(ele,type,fn)
- 綁定及執行結果:所有瀏覽器兼容,但事件觸發時,fn中this為ele,即元素,默認傳入一個事件對象實參
- 自定義行為事件綁定:on(ele,type,fn);執行:fire.call(ele,type,e);解綁:off(ele,type,fn);
- 綁定時on中的ele為元素,fire函數在調用時必須保證里面的this為元素;type自定義行為的開頭必須以my開頭;
- 綁定及執行結果:fire作為接口放在函數中執行,如果未用on綁定方法,里面無執行函數;當用on綁定方法后,就會在預留接口處執行方法;用于訂閱發布;執行的函數中的this為當前元素;
- 改變函數的this執行:processThis(fn,thisArg)即:將fn中的this指向改變為thisArg
- 執行結果:將fn中的this指向改變為thisArg,并給fn傳一個實參e,一般跟事件配合,返回一個匿名函數;
- 注意:
- 綁定自定義行為事件時,on里面的參數ele可以是元素也可以是實例對象,但事件庫主要用于給元素綁定系統行為或自定義行為,所以參數ele為元素;一般不設置實例對象;
- 代碼:
- 執行代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>事件庫最終版封裝</title> <style> body{ height: 1000px; } div{ width: 200px; height: 200px; background-color: red; } </style> </head> <body> <div id="div1">111</div> <script src="復習JS庫/01Event.js"></script> <script> var oDiv=document.getElementById("div1"); on(oDiv,"mymeinv",fn1); on(oDiv,"mymeinv",fn2); on(oDiv,"mymeinv",fn3); //off(oDiv,"mymeinv",fn3); function fn1(e) { console.log(this.innerHTML); console.log(e.pageY); } function fn2() { console.log(2); } function fn3() { console.log(3); } on(oDiv,"click",fn4); function fn4(e){ fire.call(this,"mymeinv",e); } //processThis函數驗證 function add(e) { console.log(this); console.log(e.type); } on(oDiv,"click",processThis(add,oDiv)); </script> </body> </html>
- 事件庫終極版封裝
function on(ele,type,fn) { if(/^my/gi.test(type)){//綁定的是自定義行為,必須以my開頭 //事件庫中ele均為元素 if(!ele[type]){ ele[type]=[]; } var b=ele[type]; if(b.length){ for(var i=0; i<b.length; i++){ if(b[i]===fn) return; } } b.push(fn); }else{//綁定的是系統行為,如click,mousemove等 //瀏覽器的兼容 if(ele.addEventListener){ ele.addEventListener(type,fn,false); }else{//IE瀏覽器 if(!ele["on"+type]){ ele["on"+type]=[]; //將run方法綁定到系統事件池中 ele.attachEvent("on"+type,function (e) { run.call(ele,e);//保證run中的this指向為當前元素;在IE瀏覽器下事件觸發,不會給匿名函數傳事件對象實參; }) } var a=ele["on"+type]; //去重處理,避免重復綁定 if(a.length){ for(var i=0; i<a.length; i++){ if(a[i]===fn) return; } } a.push(fn); } } } //fire函數相當于一個接口,在某個位置執行on綁定的type行為上的所有方法; function fire(type,e) { //fire中的this可以指元素,也可以指實例對象,與on中相對應; var b=this[type] || []; if(b.length){ for(var i=0; i<b.length; i++){ if(typeof b[i]==="function"){ b[i].call(this,e);//保證函數執行時,里面的this為當前this,即為元素,并傳入實參e; }else{ b.splice(i,1); i--; } } } } function run(e) { e= e || window.event; //e的兼容處理 e.target=e.srcElement; e.pageX=(document.documentElement.scrollLeft || document.body.scrollLeft)+e.clientX; e.pageY=(document.documentElement.scrollTop || document.body.scrollTop)+e.clientY; //阻止默認事件 e.preventDefault=function () { e.returnValue=false; }; //阻止冒泡 e.stopPropagation=function () { e.cancelBubble=true; }; //遍歷run執行函數,保證函數中的this為當前元素,而且給其傳實參e var a=this["on"+e.type];//this為當前元素 if(a.length){ for(var i=0; i<a.length; i++){ if(typeof a[i]==="function"){ a[i].call(this,e); }else{ a.splice(i,1); i--;//防止數組塌陷 } } } } function off(ele,type,fn) { if(/^my/gi.test(type)){ var b=ele[type]; if(b.length){ for(var i=0; i<b.length; i++){ if(b[i]===fn){ b[i]=null; break; } } } }else{ if(ele.removeEventListener){ ele.removeEventListener(type,fn,false); }else{ var a=ele["on"+type]; if(a.length){ for(var i=0; i<a.length; i++){ if(a[i]===fn){ a[i]=null; break;//性能優化; } } } } } } //改變函數的this執行 function processThis(fn,thisArg) { return function (e) { fn.call(thisArg,e); } }
2 運動庫的復習及最終版封裝
- 依賴的庫:依賴utils庫,用于接口使用時,依賴Event事件庫;
- 使用方法:
- 代碼:
animate(opt)
;為全局函數調用; - 參數:對象opt
- 必須傳的參數:1)ele:元素,指需要運動的元素;2)target:屬性值為對象,對象中的鍵值對為目標值;
- 可傳可不傳的參數:1)duration:運動總時間,默認為2000ms;2)effect:運動方式,可以是字符串,也可以是數字,默認為Linear線性運動;3)callback:不傳不執行,傳了之后執行函數,函數中this被設置為元素;
- 代碼:
- 注意點:在運動結束后,設置一個fire接口,接口的類型為myAnimate,若需要執行操作,可用on在元素身上綁定該行為的方法;fire接口中設置的this為該元素,即綁定的方法執行時,函數中的this為該元素;
- 執行結果:
- 目的:一個元素從開始位置(ele)在規定時間(duration)內,以什么樣的運動形式(effect),到達指定目的地(target),執行什么動作(callback或fire接口執行);
- 代碼:
- 執行代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>運動庫驗證</title> <style> *{ margin: 0; padding: 0; } #div1{ width: 80px; height: 80px; background-color: red; line-height: 80px; text-align: center; position: absolute; top: 10px; left:200px; opacity: 0.1; filter: alpha(opacity=10); } #div2{ width: 1px; height: 500px; margin-top: 10px; background-color: blue; position: absolute; top: 10px; left: 1100px; } </style> </head> <body> <div id="div1">物體</div> <div id="div2"></div> <script src="復習JS庫/00utils.js"></script> <script src="復習JS庫/01Event.js"></script> <script src="復習JS庫/02Animate.js"></script> <script> var oDiv1=document.getElementById("div1"); function fn1(){ //此時函數中的this為元素; console.log(this.innerHTML); this.style.border="5px solid pink"; this.innerHTML="我成功了,祝賀我吧!"; this.style.fontSize="10px"; this.style.lineHeight="10px"; } //綁定myAnimate行為,執行方法 on(oDiv1,"myAnimate",fn1); animate({ ele:oDiv1, target:{ left:1000, top:400, opacity: 0.8 }, effect:6, duration: 2000 //此時callback可以不用,可以用預留的接口,然后進行綁定執行; /*callback:function () { //默認情況下回調函數執行時,this指向window; //在調用時,用call改變this指向為ele; this.style.backgroundColor="yellow"; }*/ }) </script> </body> </html>
- 封裝代碼:
(function () { //運動形式對象 var gbEffect= { Linear: function (t, b, c, d){ //勻速 return c*t/d + b; }, EaseIn: function(t, b, c, d){ //加速曲線 return c*(t/=d)*t + b; }, EaseOut: function(t, b, c, d){ //減速曲線 return -c *(t/=d)*(t-2) + b; }, EaseBoth: function(t, b, c, d){ //加速減速曲線 if ((t/=d/2) < 1) { return c/2*t*t + b; } return -c/2 * ((--t)*(t-2) - 1) + b; }, EaseInStrong: function(t, b, c, d){ //加加速曲線 return c*(t/=d)*t*t*t + b; }, EaseOutStrong: function(t, b, c, d){ //減減速曲線 return -c * ((t=t/d-1)*t*t*t - 1) + b; }, EaseBothStrong: function(t, b, c, d){ //加加速減減速曲線 if ((t/=d/2) < 1) { return c/2*t*t*t*t + b; } return -c/2 * ((t-=2)*t*t*t - 2) + b; }, Elastic:{ In: function(t, b, c, d, a, p){ //正弦衰減曲線(彈動漸入) if (t === 0) { return b; } if ( (t /= d) == 1 ) { return b+c; } if (!p) { p=d*0.3; } if (!a || a < Math.abs(c)) { a = c; var s = p/4; } else { var s = p/(2*Math.PI) * Math.asin (c/a); } return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; }, Out: function(t, b, c, d, a, p){ //正弦增強曲線(彈動漸出) if (t === 0) { return b; } if ( (t /= d) == 1 ) { return b+c; } if (!p) { p=d*0.3; } if (!a || a < Math.abs(c)) { a = c; var s = p / 4; } else { var s = p/(2*Math.PI) * Math.asin (c/a); } return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; }, Both: function(t, b, c, d, a, p){ if (t === 0) { return b; } if ( (t /= d/2) == 2 ) { return b+c; } if (!p) { p = d*(0.3*1.5); } if ( !a || a < Math.abs(c) ) { a = c; var s = p/4; } else { var s = p/(2*Math.PI) * Math.asin (c/a); } if (t < 1) { return - 0.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; } return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b; } }, Back:{ In: function(t, b, c, d, s){ //回退加速(回退漸入) if (typeof s == 'undefined') { s = 1.70158; } return c*(t/=d)*t*((s+1)*t - s) + b; }, Out: function(t, b, c, d, s){ if (typeof s == 'undefined') { s = 3.70158; //回縮的距離 } return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; }, Both: function(t, b, c, d, s){ if (typeof s == 'undefined') { s = 1.70158; } if ((t /= d/2 ) < 1) { return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; } return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; } }, Bounce:{ In: function(t, b, c, d){ //彈球減振(彈球漸出) return c - gbEffect.Bounce.Out(d-t, 0, c, d) + b; }, Out: function(t, b, c, d){ if ((t/=d) < (1/2.75)) { return c*(7.5625*t*t) + b; } else if (t < (2/2.75)) { return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b; } else if (t < (2.5/2.75)) { return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b; } return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b; }, Both: function(t, b, c, d){ if (t < d/2) { return gbEffect.Bounce.In(t*2, 0, c, d) * 0.5 + b; } return gbEffect.Bounce.Out(t*2-d, 0, c, d) * 0.5 + c*0.5 + b; } } }; var gbEffectAry=["Linear","EaseIn","EaseOut","EaseBoth","EaseInStrong","EaseOutStrong","EaseBothStrong","Elastic-In","Elastic-Out","Elastic-Both","Back-In","Back-Out","Back-Both","Bounce-In","Bounce-Out","Bounce-Both"]; //運動庫封裝 function animate(opt) { //0 對傳入的實參值進行判斷; opt=opt || {}; if(!opt.ele) return;//如果傳參錯誤,代碼阻斷不執行; //1 新建一個對象,里面添加默認樣式 var defaultOpt={ duration: 2000, effect: "Linear" }; //2 將傳入的實參opt,所有屬性賦值給defaultOpt,如果存在,則重新賦值,如果不存在,使用默認值; for(var attr in opt){ defaultOpt[attr]=opt[attr]; } //總結:defaultOpt的作用是設置默認的屬性,如果傳入的實參里面設置了defaultOpt里面的屬性,就重新賦值,如果沒有設置,就用默認值; //下面所有代碼不再使用opt,而使用defaultOpt; //3 獲取defaultOpt里面的參數 var ele=defaultOpt.ele; var target=defaultOpt.target; var duration=defaultOpt.duration; var callback=defaultOpt.callback; var effect=defaultOpt.effect; var tempEffect=null; //4 獲取運動形式,計算參數 //4.1 獲取運動形式:判斷effect的數據類型,滿足下面兩種情況,就執行各自的代碼,如果不滿足,就使用默認值; var ary=gbEffectAry; if(typeof effect==="number"){ ary=ary[effect%ary.length].split("-"); tempEffect=ary.length>=2?gbEffect[ary[0]][ary[1]]:gbEffect[ary[0]]; }else if(typeof effect==="object"){ tempEffect=effect.length>=2?gbEffect[effect[0]][effect[1]]:gbEffect[effect[0]]; }else if(typeof effect==="string"){ tempEffect=gbEffect[effect];//此時tempEffect設置一個函數定義地址,不是函數名; } //4.2 計算傳入運動形式中的參數 var begin={},change={}; for(var attr in target){ begin[attr]=utils.css(ele,attr); change[attr]=target[attr]-begin[attr]; } var time=0; //5 添加定時器 var timer=setInterval(function () { //5.1 變量累加 time+=30; //5.2 邊界值判斷 if(time>=duration){ //5.2.1 設置邊界值 utils.css(ele,target); //5.2.2 停止定時器 clearInterval(timer); //5.2.3 執行回調函數,進行下一步操作 callback && callback.call(ele);//當callback存在的時候,執行回調函數,改變其中的this指向為元素; //增加接口,用于綁定多個操作,執行函數,如果不綁定就不會執行方法; fire.call(ele,"myAnimate"); //5.2.4 阻斷程序執行 return; } //5.3 獲取最新位置及設置最新位置 for(var attr in change){ //5.3.1 運動方式獲取最新位置; var cur=tempEffect(time,begin[attr],change[attr],duration); //5.3.2 分別設置最新位置 utils.css(ele,attr,cur); } },30) } window.animate=animate;//將私有函數設置為全局變量; })();
3 ajax庫的復習及最終版封裝
- 依賴的庫:不依賴任何庫;
- 使用方法:
- 代碼:
03myAjax(opt)
;為全局函數調用; - 參數:對象opt
- data:對象,里面的鍵值對為搜索參數;
- type:get/post/jsonp;
- get、post用于本地數據獲取,不能跨域獲取;
- jsonp用于跨域獲取,需注意的是在百度服務器中必須設置jsonp參數為cb才能獲取數據;
- 代碼:
- 代碼:
- 執行代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>封裝的ajax</title> </head> <body> <script src="JS庫終極版/03myAjax.jsjs"></script> <script> 03myAjax({ url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su", data:{wd:"zhouxingchi"}, type:"jsonp", dataType:"json", jsonp:"cb",//此處必須設置jsonp為cb,才能使用 success:function (data) { console.log(data); } }); </script> </body> </html>
- JS庫封裝代碼:
//參數:ajax({url:xxx,data:xxx,type:xxx,dataType:xxx,jsonp:xxx,fnLoading:xxx,complete:xxx,success:xxx,error:xxx,timeout}) //將對象中的屬性名和屬性值轉化為key=val&key=val的形式 function json2url(obj) { //參數:對象,返回值:字符串 //思路:對象-數組-字符串 obj.t=Math.random();//避免緩存 var ary=[]; //遍歷對象 for(var attr in obj){ ary.push(attr+"="+obj[attr]); } return ary.join("&"); } function jsonParse(strJson) { return "JSON" in window?JSON.parse(strJson):eval("("+strJson+")"); } function 03myAjax(json) { json=json||{}; //如果json中請求地址url不存在 if(!json.url) return; //參數獲取 var url=json.url; //data屬性值為一個對象,對象中為參數 var data=json.data||{}; var type=json.type||"get"; var jsonp=json.jsonp||"callback"; var timeout=json.timeout||3000; var timer=null; //四步: //1 創建一個xml對象 //每個類函數都是window的一個屬性; if(window.XMLHttpRequest){ var xml=new XMLHttpRequest(); }else{//IE6兼容處理 var xml=new ActiveXObject("Microsoft.XMLHTTP"); } //2 打開地址;3 發送請求 //get請求:參數在地址中,在url?的后面,以鍵值對的形式連接; //post請求:參數在請求體中,地址url后面不跟參數; switch(type.toLowerCase()){ case "get": xml.open("get",url+"?"+json2url(data),true); xml.send(null); break; case "post": xml.open("post",url,true); xml.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xml.send(json2url(data)); break; case "jsonp": //新建一個全局函數 var kbfd="jsonp_"+Math.random(); kbfd=kbfd.replace(".","");//函數名中不能存在小數點,所以需要替換 window[kbfd]=function (data) { json.success && json.success(data); //卸磨殺驢,干掉script document.body.removeChild(oS); oS=null; }; data[jsonp]=kbfd; //創建script標簽,設置其src,通過script發送請求 var oS=document.createElement("script"); //script中src包含url?參數&cb=kbfd oS.src=url+"?"+json2url(data); //script必須插入到頁面的底部 document.body.appendChild(oS); break; } //響應請求之前的準備 json.fnLoading && json.fnLoading(); //4 響應請求 xml.onreadystatechange=function () { if(xml.readyState===4){ //請求成功 json.complete && json.complete(); clearTimeout(timer); //判斷后臺響應成功還是失敗; if(/^2\d{2}$/.test(xml.status)){//響應成功 if(json.dataType==="json"){ json.success && json.success(jsonParse(xml.responseText)); }else{ json.success && json.success(xml.responseText); } }else{//響應失敗 json.error && json.error(xml.status); } } }; if(type==="jsonp") return; //5 等待超時 timer=setTimeout(function () { alert("您的網絡不行啊"); xml.onreadystatechange=null; },timeout); }
4 拖拽庫復習及最終版封裝
- 依賴的庫:Event事件庫
- 使用方法:
- 代碼:
var res=new Drag(opt)
;為實例創建調用; - 參數:對象opt;
- ele:必須穿,為拖拽元素;
- 執行結果:元素純凈版拖拽,無邊界值判斷,可拖拽到任何地方;
- 代碼:
- 擴展功能:
- 預留接口:給實例對象綁定了三個自定義行為:myDragDown myDragMove myDragUp
- 在鼠標按下事件中,添加自定義行為myDragDown
- 在鼠標移動事件中,添加自定義行為myDragMove
- 在鼠標抬起事件中,添加自定義行為myDragUp
- 綁定代碼:
res.on("myDragDown",fn1).on("myDragMove",fn2).on("myDragUp",fn3).off("myDragUp",fn3)
,鏈式操作綁定; - 執行結果:綁定的方法函數fn1,fn2等,函數中的this為實例對象,并傳入事件對象e;
- 預留接口:給實例對象綁定了三個自定義行為:myDragDown myDragMove myDragUp
- 代碼:
- 執行代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>拖拽Drag庫封裝驗證</title> <style> div{ width: 200px; height: 200px; background-color: red; position: absolute; left: 0; top: 0; } </style> </head> <body> <div id="div">111</div> <script src="JS庫終極版/01Event.js"></script> <script src="JS庫終極版/04Drag.js"></script> <script> var oDiv=document.getElementById("div"); var res=new Drag({ ele:oDiv }); res.on("myDragDown",fn1).on("myDragMove",fn2).on("myDragUp",fn3).off("myDragUp",fn3);//鏈式操作 function fn1() { console.log(this);//this為實例 console.log(1) } function fn2() { console.log(2) } function fn3() { console.log(3) } </script> </body> </html>
- JS封裝代碼:
//EventEmitter類:給實例對象的自定義行為綁定多個方法,訂閱發布執行 function EventEmitter() {} EventEmitter.prototype.on=function (type,fn) { if(!this[type]){ this[type]=[]; } var a=this[type]; if(a.length){ for(var i=0; i<a.length; i++){ if(a[i]===fn) return; } } a.push(fn); return this;//進行鏈式操作 }; EventEmitter.prototype.fire=function(type,e){ //保證fire函數執行時,里面的this為實例對象; var a=this[type] || []; if(a.length){ for(var i=0; i<a.length; i++){ if(typeof a[i]==="function"){ a[i].call(this,e);//保證函數執行時,里面的this為實例對象,并傳事件對象實參; }else{ a.splice(i,1); i--; } } } }; EventEmitter.prototype.off=function (type,fn) { var a=this[type]; if(a.length){ for(var i=0; i<a.length; i++){ if(a[i]===fn){ a[i]=null; break; } } } }; //Drag類:拖拽 function Drag(opt) { opt=opt||{}; if(!opt.ele) return; this.ele=opt.ele; this.disX=null; this.disY=null; this.DOWN=null; this.MOVE=null; this.UP=null; this.init(); } //原型鏈繼承 Drag.prototype=new EventEmitter(); //原型鏈繼承后,原型上沒有自己類的constructor屬性,需要重新設置 Drag.prototype.constructor=Drag; //原型上公共方法 Drag.prototype.init=function () { //綁定down事件; this.DOWN=processThis(this.down,this); on(this.ele,"mousedown",this.DOWN); }; Drag.prototype.down=function (e) { //獲取鼠標相對于元素的位置disX,disY this.disX=e.clientX-this.ele.offsetLeft; this.disY=e.clientY-this.ele.offsetTop; //綁定move,up事件 this.MOVE=processThis(this.move,this); this.UP=processThis(this.up,this); if(this.ele.setCapture){//IE瀏覽器 this.ele.setCapture();//焦點捕獲 on(this.ele,"mousemove",this.MOVE); on(this.ele,"mouseup",this.UP); }else{//標準瀏覽器 //將事件綁定到document上,阻止默認事件發生; on(document,"mousemove",this.MOVE); on(document,"mouseup",this.UP); e.preventDefault(); } this.fire("myDragDown",e);//添加接口,實例對象調用fire公共方法,自定義行為是myDragDown }; Drag.prototype.move=function (e) { //獲取新位置,無邊界值判斷 var l=e.clientX-this.disX; var t=e.clientY-this.disY; //設置新位置 this.ele.style.left=l+"px"; this.ele.style.top=t+"px"; this.fire("myDragMove",e);//添加接口,實例對象調用fire公共方法,自定義行為是myDragMove }; Drag.prototype.up=function (e) { if(this.ele.releaseCapture){ this.ele.releaseCapture();//釋放焦點捕獲; off(this.ele,"mousemove",this.MOVE); off(this.ele,"mouseup",this.UP); }else{ off(document,"mousemove",this.MOVE); off(document,"mouseup",this.UP); } this.fire("myDragUp",e);//添加接口,實例對象調用fire公共方法,自定義行為是myDragUp };
5 myBind函數封裝
- 依賴的庫:不依賴任何庫
- 使用方法:
- 代碼:
fn1.myBind(oDiv,2,3)
; - 調用:函數名調用,myBind為函數類原型上的方法,所有函數均能調用;
- 參數:
- 第一個參數:thisArg,必須傳,用于改變函數的this指向,不改變賦值null;
- 第二個參數:實參,可傳可不傳,如果需要實參則傳,不需要則不傳;
- 默認傳入一個事件對象實參;多與事件配合;
- 返回值為一個匿名函數,即函數的預處理;
- 執行結果:改變fn1函數中的this指向為thisArg,給fn1傳實參,與事件對象配合默認傳入一個事件對象實參;返回一個匿名函數;
- 代碼:
- 代碼:
- 執行代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>myBind函數封裝驗證</title> <style> div{ width: 200px; height: 200px; background-color: red; } </style> </head> <body> <div id="div1">1111</div> <script src="JS庫終極版/05myBind.js"></script> <script> var oDiv=document.getElementById("div1"); function fn1(n,m,e){ console.log(this.innerHTML); console.log(n+m); console.log(e.pageX); } oDiv.onclick=fn1.myBind(oDiv,2,3); </script> </body> </html>
- JS封裝代碼:
(function () { Function.prototype.myBind=function (thisArg) { var outArg=[].slice.call(arguments,1); if("bind" in Function.prototype){ return this.bind.apply(this,[thisArg].concat(outArg)); } var _this=this; return function (e) { e=arguments.length===0?window.event:e; //IE瀏覽器下的兼容處理 e.target=e.srcElement; e.pageX=(document.documentElement.scrollLeft ||document.body.scrollLeft)+e.clientX; e.pageY=(document.documentElement.scrollTop || document.body.scrollTop)+e.clientY; //阻止默認事件 e.preventDefault=function () { e.returnValue=false; }; //阻止冒泡 e.stopPropagation=function () { e.cancelBubble=true; }; return _this.apply(thisArg,outArg.concat(e)); } }; })();