- 浏览: 36295 次
- 性别:
- 来自: 武汉
文章分类
- 全部博客 (36)
- js笔记 (11)
- extjs笔记 (4)
- openlayers笔记 (3)
- html笔记 (1)
- tomcat (1)
- ajax笔记 (1)
- css (2)
- 工作汇报 (2)
- GIS (3)
- SDK API (1)
- openlayers源码解读 (1)
- 单元测试 (0)
- bug积累 (1)
- 经济学基础 (0)
- 竞足 (0)
- 性能优化 (0)
- 互联网时代笔记 (0)
- 公司数据平台项目笔记 (0)
- 待解决的问题 (0)
- web (0)
- webapp (0)
- 生活 (0)
- 用户体验 (0)
- angularjs (0)
- 项目后台 (0)
- Java (1)
- 电力 (0)
- 算法 (0)
- 数据库 (1)
- sql (0)
- avalon (1)
- arcMap (0)
- 公共信息云平台笔记 (0)
- 工具使用 (0)
- arcgis js api笔记 (0)
- maven (0)
最新评论
你相信么,在JavaScript只需一个函数5行代码即可实现完整的面向方面AOP编程功能。这5行代码的功能包括:
1、无限层次的函数无害拦截
2、函数执行前拦截
3、检查函数的参数值
4、重新设定函数的参数值
5、函数执行后拦截
6、检查函数执行后的返回结果
7、重新设定函数的返回结果
虽然动态函数式语言的效率是一个存在的问题,但是对于它的高度灵活性,简直让人令人惊叹不已,剧赞。
这个小小的函数源自于和爱明兄的一次讨论:在javascript中不修改源代码的形式扩充新功能的完美方式。
至于为啥要不直接修改别人源代码库,你想,当你辛苦修改后,人家发布了一个新版本,你是不是又要重新
修改一次?如果修改的地方少还好,多了的话,嘿嘿!所以,不是你的东西,最好不要动,除非你确定要自
己完全维护所有的代码(如果你实在太闲)。
为了给开发人员一个榜样,俺不得不写一个patch样例,最开始俺写的patch方式是这样滴:
FCKEditingArea.prototype.FckMediaStart = FCKEditingArea.prototype.Start;
FCKEditingArea.prototype.Start = function( html, secondCall )
{
var sHeadExtra = '<link href="' + FCKConfig.PluginsPath + 'media/css/fck_media.css" rel="stylesheet" type="text/css" _fcktemp="true" />' ;
html = html.replace( FCKRegexLib.HeadCloser, sHeadExtra + '$&' ) ;
return this.FckMediaStart(html, secondCall);
}
俺觉得这种补丁方式是不太让我满意的
爱民兄提到他喜欢这样patch方式:
FCKEditingArea.prototype.Start = function( func ) {
return function( html ) {
html = html.replace( FCKRegexLib.HeadCloser, sHeadExtra + '$&' ) ;
return func.apply(this, arguments);
}
}(FCKEditingArea.prototype.Start);
这种方式的确不存在漏洞了,perfect,但是却把我彻底弄懵了,看得我头大啊!琢磨了好久才算明白过来。
不过从管理角度考虑,如果程序中到处都是这样的方式,那么将大大降低程序的可读性,增加维护代码的成本
(ps,要开发维护这样的代码,你不得不请JS高级程序员才行)。
为了限制匿名函数的滥用导致的可读性下降,俺写了一个Inject()函数的雏形(将匿名函数的使用限制在其中),
经过爱民兄修改,然后又是讨论,然后我们又修改,如此反复,达到这个最终版本(也许还不是,谁知道呢)。
好了,荣誉归于爱民,臭鸡蛋归于俺,闲话少说,看看代码吧,不算上注释,这个Inject函数正好5行。如果你清楚
的知道匿名函数的特点,那么这个函数,你就不难看懂,否则你就只能管用了。用法在注释的例子里,够简单吧。
function Inject( aOrgFunc, aBeforeExec, aAtferExec ) {
return function() {
if (typeof(aBeforeExec) == 'function') arguments = aBeforeExec.apply(this, arguments) || arguments;
//convert arguments object to array
var Result, args = [].slice.call(arguments);
args.push(aOrgFunc.apply(this, args));
if (typeof(aAtferExec) == 'function') Result = aAtferExec.apply(this, args);
return (typeof(Result) != 'undefined')?Result:args.pop();
}
}
使用新的Inject方式的代码如下:
FCKMediaProcessor.EditingArea_StartBefore = function ( html, secondCall )
{
var sHeadExtra = '<link href="' + FCKConfig.PluginsPath + 'media/css/fck_media.css" rel="stylesheet" type="text/css" _fcktemp="true" />' ;
html = html.replace( FCKRegexLib.HeadCloser, sHeadExtra + '$&' ) ;
//在执行前修改了参数值,所以返回修改后的参数
return arguments;
}
FCKEditingArea.prototype.Start = Inject(FCKEditingArea.prototype.Start, FCKMediaProcessor.EditingArea_StartBefore);
ok,下面将继续增强 Inject的功能,将会把浪子提到的控制原函数是否执行加上。
本增强版本和上面的Inject函数的版本使用上略有差别,使用规范如下:
执行前调用(BeforeExec)
如果修改了参数值,必须这样返回修改的参数: return new Arguments(arguments);
如果没有返回值或者返回undefined那么正常执行,返回其它值表明不执行原函数,该值作为替代的原函数返回值。
执行后调用(AfterExec)
如果希望取得函数的返回值,必须在原参数表后面增加一个参数: result
如果希望知道原函数是否被执行,那么必须在 result参数的后面再增加一个参数: isDenied 该值为真表明没有执行原函数
如果希望修改函数的返回值,那么你只要简单的把修改后的值返回即可。
示例:假设我们要拦截一个 doTest 函数,修改它的参数值a,在原参数值上+1,并在它的函数返回值上也+1:
//定义测试函数 doTest
var doTest = function (a) {
alert('dotest 运行中');
return a;
};
function beforeTest(a) {
alert('执行前参数: a='+a);
a += 1;
return new Arguments(arguments);
}
function afterTest(a, result, isDenied) {
//这里不会体现出参数a的改变,如果原函数改变了参数a。因为在js中所有参数都是值参。
alert('执行后参数: a='+a+'; result='+result+';isDenied='+isDenied);
return result+1;
}
//注入该doTest函数
doTest = Inject(doTest, beforeTest, afterTest);
//执行 doTest并显示结果
alert (doTest(2));
和爱民兄谈论后,修订后的新的Inject函数如下,这下功能全了,具体代码也不过十多行:
function Arguments(args) {
//convert arguments object to array
this.value = [].slice.call(args);
}
function Inject( aOrgFunc, aBeforeExec, aAtferExec ) {
return function() {
var Result, isDenied=false, args=[].slice.call(arguments);
if (typeof(aBeforeExec) == 'function') {
Result = aBeforeExec.apply(this, args);
if (Result instanceof Arguments) //(Result.constructor === Arguments)
args = Result.value;
else if (isDenied = Result !== undefined)
args.push(Result)
}
!isDenied && args.push(aOrgFunc.apply(this, args)); //if (!isDenied) args.push(aOrgFunc.apply(this, args));
if (typeof(aAtferExec) == 'function')
Result = aAtferExec.apply(this, args.concat(isDenied));
else
Result = undefined;
return (Result !== undefined ? Result : args.pop());
}
}
注:本文转自http://blog.sina.com.cn/s/blog_67b072ce0100ipza.html
发表评论
-
框架学习方法总结
2016-09-30 21:55 0学习一门框架,了解他是什么,能解决现实总的什么问题?他的更新日 ... -
webstorm编译typescript配置
2016-09-09 11:09 0写此文的目的是希望源文件(ts存放目录)与编译文件(js文 ... -
react生态圈讲座笔记
2016-07-06 11:31 01.react可以做到前后端同构,解决了页面首次打开速度慢 ... -
innerHTML,outerHTML,innerText,outerText
2016-01-29 17:24 0一张图好说话,如图:innerhtml_outerhtml. ... -
javascrpit设计模式之掺合模式(Mixin)
2016-01-25 22:49 0.。。。 -
iframe兼容性问题
2015-07-06 23:38 01.frame的onload事件在ie8下不会触发:docu ... -
js讲座笔记-编写js独有风格的代码
2015-05-20 23:53 0函数式编程,不是函数编程,是函数式编程是一种只关注输入与输 ... -
定制jquery包
2015-03-10 14:25 0jquery除了 核心模块(core)和 选择器(selec ... -
了解javascript中的prototype与 __proto__
2015-03-03 23:52 669我们先来看一个函数。 function person() ... -
javascript 创建对象的几种方式
2015-03-03 00:42 0js中创建对象有以下几种方式: 1.object构造函数和 ... -
bind可以改变函数执行的上下文
2015-03-02 11:50 613javascript有改变函数上下文的能力:原生的实现方式 ... -
string类型笔记
2014-10-29 17:45 0html页面里面,需要对页面设置编码方式,否则string在判 ... -
获取浏览器可视区宽高的属性
2014-07-07 19:24 0document.documentElement.clien ... -
onload事件讲解
2012-12-02 11:25 01.onload事件在什么时候发生? 2.onload事件的 ... -
js事件传播详解
2012-12-02 11:23 01.什么是事件传播? 2.为什么会出现事件传播? 3.事件 ... -
函数相关基础一
2012-11-25 23:19 01.函数(或者叫方法)的定义 函数一般有三种定义方式 ... -
js恶心的逻辑
2011-11-23 12:15 891例子一: var o={flag:0}; var test=o ... -
onclick事件在脚本中与在html中的区别
2011-09-24 15:57 1028onclick在html中的写法:<a onClick= ... -
GIS Web前端设计规则
2011-09-22 22:24 8311.程序员在设计一套前 ... -
创建闭包的一种有趣的写法
2011-06-07 18:21 6311.var Class2 = function() { ...
相关推荐
JavaScript实现AOP的思路? 通常,在 JavaScript 中实现 AOP,都是指把一个函数“动态织入”到另外一个函数之中,具体的实现技术有很多,下面我用扩展 Function.prototype 来做到这一点。请看下面代码:
* 闭包技术:一种特殊的函数,可以访问外部函数的变量,用于实现AOP。 * JavaScript AOP基本功能:使用闭包技术实现的AOP基本功能,可以将业务逻辑和非业务逻辑分离,从而提高软件的可维护性和可重用性。
在JavaScript中实现AOP,可以通过不同的方式来完成。文中提到了三种通知类型,分别是前置通知(before)、后置通知(after)、环绕通知(around)。它们的作用如下: 1. 前置通知(before):在方法执行之前执行的...
在JavaScript中实现AOP还可以借助第三方库,如`aspectjs`或`aop-js`。这些库提供了一套API,用于定义切面、通知(advises,如前置通知、后置通知、环绕通知等)和连接点(join points)。这些库可以帮助开发者更...
在 JavaScript 中实现 AOP,通常采用两种主要方法:代理模式(Proxy)和装饰器(Decorator)。代理模式通过在目标对象前创建一个代理,控制对目标对象的访问,可以在调用目标方法前后插入额外的行为。装饰器模式则是...
通过以上内容,我们可以了解到在JavaScript中实现AOP编程的原理和技术细节。这不仅包括AOP的基本概念、实现方式,还包括了如何将AOP应用到实际项目中的示例和潜在的注意事项。这些知识点对于理解面向切面编程,以及...
本项目是一个使用JavaScript实现的相册,旨在提供一种动态、直观的方式来展示和浏览图片。以下将详细介绍这个JavaScript相册的实现原理和相关知识点。 1. **DOM操作**:JavaScript通过Document Object Model(DOM)...
JavaScript AOP(面向切面编程)是一种...以上介绍的知识点不仅涵盖了AOP编程的基本概念,还涉及了具体的JavaScript实现技术。对于希望深入学习和应用JavaScript AOP编程的开发者来说,理解和掌握这些知识点非常重要。
AOP编程技术分享,包括iOS和javascript等多个平台实现
“源码”标签表明这个项目包含了实现AOP框架的原始代码,对于学习和理解JavaScript AOP工作原理非常有价值。而“工具”标签可能意味着这个框架可以作为开发工具,帮助开发者更方便地在JavaScript应用中应用AOP概念。...
在JavaScript中,AOP同样能够提供代码重构、增强模块间解耦、代码复用等优点。下面将根据文档提供的内容,详细解释在JavaScript中如何使用AOP来改善代码。 1. 防止window.onload被二次覆盖 在JavaScript中,window....
5.AOP Jquery [jQuery][9] [jQuery架构设计与实现][10] [jQuery选择器库][11] [zepto][12] 1.jQuery 插件推荐 2. jQuery 中 closure Javascript-Design-Pattern 1. Singleton-Pattern 2. Chaining 3.Factory-...
给出的代码实现了一个简单的AOP装饰器模式,用于在方法执行前后插入额外的行为。装饰器模式是一种设计模式,它可以动态地给一个对象添加一些额外的职责,使得我们可以将关注点分离,保持代码的整洁和可扩展性。 ...
JavaScript 中的 AOP 实现虽不如 Java 或 .NET 那样成熟,但依然可以通过一些技巧实现类似功能。 在 AOP 中,"通知" 是执行切面逻辑的关键部分。有四种主要的通知类型: 1. 前置通知(Before Advice):在目标方法...
本文将详细解析标题和描述中提到的“商城系统源码”,以及其技术栈Spring MVC、AOP、MyBatis、Ajax和JavaScript,并结合文件名称"shop",探讨这些技术在构建一个商城系统中的应用。 首先,商城系统是电子商务平台的...