还有,“通过事件机制,可以将类设计为独立的模块,通过事件对外通信,提高了程序的开发效率。”。相信C#程序员对事件的好处是深有体会的。好了,Code is cheap.看代码: function class1() { // 最简单的事件设计模式 } class1.prototype = { show: function () { this .onShow(); }, onShow: function () { } } function test() { var obj = new class1(); obj.onShow = function () { alert( " test " ); } obj.show(); } 下面看看如何给事件处理程序传递参数: // 将有参数的函数封装为无参数的函数 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(); // 两个都移除,一个也不显示 } 关于自定义事件的学习先到这里。
推荐阅读
JavaScript 提升运行速度之循环篇 译文
这篇着重讲第一个原因。最后给出了一个开发模式,替换传统的循环结构,可以完全避免脚本失控的状况发生。
原文标题:Speed up your JavaScript, Part 1 原文作者:Nicholas C. Zakas 在我 上一篇帖子 (译文 ) 中>>>详细阅读
本文标题:javascript 自定义事件初探
地址:http://www.17bianji.com/kaifa2/JS/28256.html
1/2 1