[设计模式]JavaScript钩子机制的应用场景与实现
来源:互联网 发布:淘宝网天猫邻家美妞儿 编辑:程序博客网 时间:2024/06/07 11:00
当我们面对比较复杂的前端项目时,我们经常会采用模块化的方式来对JavaScript代码进行解耦,以方便对代码的管理和维护,以下是一个简单的立即执行函数实现的模块化例子:
var Common = (function(){ var func = function(){ // 全局公用方法 } return { func : func }})();var ModuleA = (function(){ var _count = 1; var init = function(){ // 独立模块逻辑 } var getCount = function(){ return _count; } return { init : init, getCount : getCount }})();
模块只对外暴露外部需要的接口,而外部模块不需要关心其内部的运行逻辑,只需要知道调用接口的方式和返回结果,这样就实现了模块的“低耦合,高内聚”。
看起来很美好,可是当项目的逻辑变的越来越复杂时,比如A模块中某个针对全局公用的逻辑,可能在B模块的某种特定情况下需要进行一些额外的逻辑操作,该怎么办呢?
var Common = (function(){ var func = function(){ // 全局公用方法 if(typeof ModuleA != 'undefined' && ModuleA.getCount() > 0){ // 模块A需要进行的额外逻辑操作 } } return { func : func }})();var ModuleA = (function(){ var _count = 1; var init = function(){ // 独立模块逻辑 } var getCount = function(){ return _count; } return { init : init, getCount : getCount }})();
不知道当你看到Common.func中间的那一坨东西的时候,会不会突然怒吼一声:“卧槽,尼玛怎么这么恶心!”= =。。
明明是A模块的逻辑,却恶心地出现在了公用模块里,如果这样的特殊逻辑多起来之后,Common模块会不会变成这样?
var Common = (function(){ var func = function(){ // 全局公用方法 if(typeof ModuleA != 'undefined' && ModuleA.getCount() > 0){ // 模块A需要进行的额外逻辑操作 } if(typeof ModuleB != 'undefined' && ModuleB.getWhat() != 'something'){ // 模块B需要进行的额外逻辑操作 } // ... if(typeof ModuleZ != 'undefined' && ModuleB.isWhat() !== false){ // 模块Z需要进行的额外逻辑操作 } } return { func : func }})();
天哪,简直无法忍受。。
如果。。如果有这么一个钩子(Hook),可以把额外的逻辑代码挂在Common.func上,而Common.func执行的时候顺便把钩子上挂着的代码也执行了,那该多好啊。。这样的话既可以实现特殊的额外操作,又可以保持模块的低耦合和高内聚:
var Common = (function(){ var func = function(){ // 执行挂在这个方法的钩子上的所有额外逻辑代码 Hook.doActions(); // 全局公用方法 } return { func : func }})();var ModuleA = (function(){ var _count = 1; var init = function(){ // 用钩子把额外的逻辑挂到Common.func上 Hook.addAction(Common.func, function(){ if(_count > 0){ // 增加的额外逻辑操作 console.log('看看执行到没?'); } }); // 独立模块逻辑 } var getCount = function(){ return _count; } return { init : init, getCount : getCount }})();
没有不可能。借鉴了一下WordPress的Hook机制,一个基于JavaScript钩子机制模块就实现了。
当然,一个完整的钩子机制需要考虑的并不像上面说的那么简单,具体的实现大家请看代码,或者懒得看的可以自己尝试实现,我就不在赘述了:
/** * 钩子模块(动作是对方法的逻辑进行补充,过滤器是对方法的返回值进行处理) * * @author Lanfei * @date 2013.10.28 * * function handler(num1, num2){ * Hook.doActions(); * var value = num1 + num2; * return Hook.applyFilters(value); * } * console.log('before hook:'); * console.log(handler(1, 2)); * function action(num1, num2){ * console.log('the numbers are ' + num1 + ' and ' + num2 + '.'); * } * function filter(value){ * return 'the result is ' + value + '.'; * } * Hook.addAction(handler, action); * Hook.addFilter(handler, filter); * console.log('after hook: '); * console.log(handler(1, 2)); * */var Hook = (function(){ var addAction = function(method, action, priority){ _initHook(method); var actions = method['__hooks__'].actions; actions.push({ action : action, priority : priority || 10 }); actions.sort(_compare); } var doActions = function(){ var method = Hook.doActions.caller; _initHook(method); var actions = method['__hooks__'].actions; if(arguments.length == 0){ arguments = method.arguments; } for(var i in actions){ if(actions[i].action.apply(method, arguments) === false){ return false; } } } var hasAction = function(method, action){ _initHook(method); var actions = method['__hooks__'].actions; if(actions.length > 0 && action !== undefined){ for(var i in actions){ if(actions[i].action == action){ return true; } } return false; }else{ return actions.length > 0; } } var removeAction = function(method, action){ _initHook(method); var actions = method['__hooks__'].actions; if(actions.length > 0){ if(action !== undefined){ for(var i in actions){ if(actions[i].action == action){ delete actions[i]; return; } } }else{ method['__hooks__'].actions = []; } } } var addFilter = function(method, filter, priority){ _initHook(method); var filters = method['__hooks__'].filters; filters.push({ filter : filter, priority : priority || 10 }); filters.sort(_compare); } var applyFilters = function(value){ var method = Hook.applyFilters.caller; _initHook(method); var filters = method['__hooks__'].filters; for(var i in filters){ value = filters[i].filter.call(method, value); } return value; } var hasFilter = function(method, filter){ _initHook(method); var filters = method['__hooks__'].filters; if(filters.length > 0 && filter !== undefined){ for(var i in filters){ if(filters[i].filter == filter){ return true; } } return false; }else{ return filters.length > 0; } } var removeFilter = function(method, filter){ _initHook(method); var filters = method['__hooks__'].filters; if(filters.length > 0){ if(filter !== undefined){ for(var i in filters){ if(filters[i].filter == filter){ delete filters[i]; return; } } }else{ method['__hooks__'].filters = []; } } } var _compare = function(hook1, hook2){ return hook1.priority < hook2.priority; } var _initHook = function(method){ if(! method['__hooks__']){ method['__hooks__'] = { actions : [], filters : [] }; } } return { addAction : addAction, doActions : doActions, hasAction : hasAction, removeAction : removeAction, addFilter : addFilter, applyFilters : applyFilters, hasFilter : hasFilter, removeFilter : removeFilter };})();
ps:原文地址:http://www.clanfei.com/2013/10/1730.html/comment-page-1
0 0
- [设计模式]JavaScript钩子机制的应用场景与实现
- JS钩子的机制与实现
- Windows的钩子实现与应用
- 设计模式应用场景
- 设计模式应用场景
- 设计模式应用场景
- 设计模式 应用场景
- 设计模式 应用场景
- 设计模式应用场景
- 设计模式应用场景
- 设计模式 应用场景
- 设计模式应用场景
- 各种设计模式的应用场景
- 常用设计模式的应用场景
- 常用设计模式的应用场景
- java设计模式的应用场景
- JAVA设计模式的应用场景
- Java设计模式的应用场景
- Java基础--字符串、正则表达式
- mysql中文乱码
- 用workspace创建静态库后的配置
- 查询,珍爱网ID,百合网ID,世纪佳缘ID,有缘网ID
- 我的java学习笔记(19)关于代理
- [设计模式]JavaScript钩子机制的应用场景与实现
- Java基础--反射
- 在控件中显示JPG图片
- 出现NSScanner: nil string argument libc++abi.dylib: terminate_handler unexpectedly threw an exception
- JSP原理(二)
- 欢迎使用CSDN-markdown编辑器
- avl树实现
- JAVA学习笔记(五十七)- 常用设计模式
- Hama框架学习(一) 从源码角度分析job的提交和运行过程