function Student(){}Student.prototype = { sayHello:function(){this.onSayHello();}, onSayHello:function(){} };function test() { var stu = new Student(); stu.sayHello = function() { alert("ok"); } stu.sayHello();}window.onload = test;
下面看看如何給事件處理常式傳遞參數:
// 將有參數的函數封裝為無參數的函數 function createFunction(obj, strFunc) { var args = []; // 定義args 用於儲存傳遞給事件處理常式的參數 if ( ! obj) obj = window; // 如果是全域函數則obj=window; // 得到傳遞給事件處理常式的參數 for ( var i = 2 ; i < arguments.length; i ++ ) args.push(arguments[i]); // 用無參數函數封裝事件處理常式的調用 return function () { obj[strFunc].apply(obj, args); // 將參數傳遞給指定的事件處理常式 } } function class1() { } class1.prototype = { show: function () { this .onShow(); }, onShow: function () { } } function objOnShow(userName) { alert( " hello, " + userName); } function test() { var obj = new class1(); var userName = " test " ; obj.onShow = createFunction( null , " objOnShow " , userName); obj.show(); }
"因為事件機制僅傳遞一個函數的名稱,不帶有任何參數的資訊,所以無法傳遞參數進去",這是後話了,“要解決這個問題,可以從相反的思路去考慮,不考慮怎麼把參數傳進去,而是考慮如何構建一個無需參數的事件處理常式,該程式是根據有參數的事件處理常式建立的,是一個外層的封裝。”,這裡的“該程式”就是 createFunction函數,它巧妙地利用apply函數將帶參數的函數封裝為無參數函數。最後我們看看如何?自訂事件的多綁定:
// 使自訂事件支援多綁定 // 將有參數的函數封裝為無參數的函數 function createFunction(obj, strFunc) { var args = []; // 定義args 用於儲存傳遞給事件處理常式的參數 if ( ! obj) obj = window; // 如果是全域函數則obj=window; // 得到傳遞給事件處理常式的參數 for ( var i = 2 ; i < arguments.length; i ++ ) args.push(arguments[i]); // 用無參數函數封裝事件處理常式的調用 return function () { obj[strFunc].apply(obj, args); // 將參數傳遞給指定的事件處理常式 } } function class1() { } class1.prototype = { show: function () { if ( this .onShow) { for ( var i = 0 ; i < this .onShow.length; i ++ ) { this .onShow[i](); } } }, attachOnShow: function (_eHandler) { if ( ! this .onShow) this .onShow = []; this .onShow.push(_eHandler); } } function objOnShow(userName) { alert( " hello, " + userName); } function objOnShow2(testName) { alert( " show: " + testName); } function test() { var obj = new class1(); var userName = " your name " ; obj.attachOnShow(createFunction( null , " objOnShow " , userName)); obj.attachOnShow(createFunction( null , " objOnShow2 " , " test message " )); obj.show(); }
我們看到,attachOnShow方法實現的基本思想是對數組的push操作,其實我們還可以在事件執行完成之後,移除事件處理函數,下面單獨實現:
// 將有參數的函數封裝為無參數的函數 function createFunction(obj, strFunc) { var args = []; // 定義args 用於儲存傳遞給事件處理常式的參數 if ( ! obj) obj = window; // 如果是全域函數則obj=window; // 得到傳遞給事件處理常式的參數 for ( var i = 2 ; i < arguments.length; i ++ ) args.push(arguments[i]); // 用無參數函數封裝事件處理常式的調用 return function () { obj[strFunc].apply(obj, args); // 將參數傳遞給指定的事件處理常式 } } function class1() { } class1.prototype = { show: function () { if ( this .onShow) { for ( var i = 0 ; i < this .onShow.length; i ++ ) { this .onShow[i](); } } }, attachOnShow: function (_eHandler) { // 附加事件 if ( ! this .onShow) { this .onShow = []; } this .onShow.push(_eHandler); }, detachOnShow: function (_eHandler) { // 移除事件 if ( ! this .onShow) { this .onShow = []; } this .onShow.pop(_eHandler); } } function objOnShow(userName) { alert( " hello, " + userName); } function objOnShow2(testName) { alert( " show: " + testName); } function test() { var obj = new class1(); var userName = " your name " ; obj.attachOnShow(createFunction( null , " objOnShow " , userName)); obj.attachOnShow(createFunction( null , " objOnShow2 " , " test message " )); obj.show(); obj.detachOnShow(createFunction( null , " objOnShow " , userName)); obj.show(); // 移除一個,顯示剩餘的一個 obj.detachOnShow(createFunction( null , " objOnShow2 " , " test message " )); obj.show(); // 兩個都移除,一個也不顯示 }