使用AOP改善javascript代码

Aop又叫面向切面编程,用过spring的同学肯定对它非常熟悉,而在js中,AOP是一个被严重忽视的技术点,这篇就通过下面这几个小例子,来说说AOP在js中的妙用.

1, 防止window.onload被二次覆盖.
2,无侵入的统计代码.
3, 分离表单请求和校验.
4,给ajax请求动态添加参数.
5,职责链模式.
6, 组合代替继承.

先给出before和after这2个“切面”函数. 顾名思义,就是让一个函数在另一个函数之前或者之后执行,巧妙的是,before或者after都可以和当前的函数公用this和arguments, 这样一来供我们发挥的地方就多着了.

处理window.onload被二次覆盖.

前段时间看到QQ群里有个人问问题,要改写window.onload, 怎么才能不把以前的window.onload函数覆盖掉.

最原始的方案肯定是直接在原来的window.onload里添上你的新代码.

这样的坏处非常明显,需要去改动原有的函数, 是侵入性最强的一种做法.

另外一种稍微好点的方案是用中间变量保存以前的window.onload;

这样一来,多了一个讨厌的中间变量__onload, 来管理它也要花费一些额外的成本.

试想一下这个场景,当人觉得天气冷,出门的时候很自然选择穿上一件貂皮大衣,而不是把自己的皮扯掉换成貂皮. 动态装饰的好处就体现出来了,完全不会侵入之前的函数.

无侵入的统计代码

本身跟逻辑没有任何关联的统计代码要被硬插进函数里, 这点相信很多搞过上报的同学都很不爽. 比如下面这段代码, 用来统计一个创建1000个节点的函数在用户的电脑上要花费多少时间.

用aop的方式,不再需要在函数内部做改动,先定义一个通用的包装器.

只要一行代码,便能给任何函数都加上统计时间的功能.

分离表单请求和校验

我们在提交表单之前经常会做一些校验工作,来确定表单是不是应该正常提交. 最糟糕的写法是把验证的逻辑都放在send函数里面.

而更好的方式是把所有的校验规则用策略模式放到一个集合里,返回false或者true来决定是否通过验证. 这样可以随意的选择和更换校验规则.

这样还有一个缺点,校验和发送请求这2个请求耦合到了一个函数里面, 我们用aop来把它们分离开来, 把validata做成插件化,真正的即插即用. 只需把send函数改成:

过最前面Function.prototype.before的代码不难看出,我们约定,当前一个函数返回false, 就会阻断下一个函数的执行, 所以当validata返回false的时候, 便不再继续执行send. 而因为之前提到的before函数可以和当前函数公用this和arguments, 所以value参数也能顺利的传递到validata函数里.

给ajax请求动态添加参数

第一个例子里window.onload是用的after后置装饰, 这里是用before前置装饰. 在ajax请求之前动态添加一些参数.

我们遇到过很多跨域的请求, jsonp和iframe都是很常用的方式. 之前在我们的项目里,用参数retype=jsonp表示是jsonp请求, retype=iframe表示是iframe请求. 除此之外这2个请求的参数没有任何区别. 那么可以用before把retype参数动态装饰进去.

先定义一个ajax请求的代理函数.

这个函数里面没有逻辑处理和分支语句,它也不关心自己是jsonp请求还是iframe请求. 它只负责发送数据, 是一个单一职责的好函数.

接下来在发送请求前放置一个before装饰器.

开始发送请求:

职责链模式.

职责链模式在js中典型的应用场景是事件冒泡. 将所有子节点和父节点连成一条链,并沿着这条链传递事件,直到有一个节点能够处理它为止. 职责链模式是消除过多的if else语句的神器.

拿最近做的一个需求来举例, 有个文件上传的功能, 提供了控件,html5, flash, 表单上传这4种上传方式. 根据它们的优先级以及浏览器支持情况来判断当前选择哪种上传方式. 在我进行改造之前,它的伪代码大概是这样:

当然实际的代码远不只这么多,其中还包括了各种控件初始化,容错等情况。有天我需要屏蔽掉flash,看起来是很简单的需求,但难度实际跟在心脏旁边拆掉一根毛线血管类似.

如果试试职责链模式呢, 看看事情将变得多简单:

第一步先改写之前的after函数,使得返回一个对象时阻断职责链的传递,而返回null时继续传递请求。

接下来把每种控件的创建方式都包裹在各自的函数中, 确保没有逻辑交叉和相互污染.

最后用职责链把它们串起来:

可以预见,某天我又需要屏蔽掉flash, 那时的我只需要改动这一行代码. 改成:

组合代替继承

很多时候我们在设计程序的时候,会遇到使用组合还是继承的问题. 通常来讲, 使用组合更灵活轻巧. 还是拿之前文件上传来举例.

我定义了一个超类Upload, 衍生出4个子类.
Plugin_Upload, Html5_Upload, Flash_Upload以及Form_Upload.

Plugin_Upload会继承父类,得到Upload的大部分功能, 然后对控件上传的一些特性进行个性定制. 比如其它3种上传方式都是选择文件后便开始上传. 而控件上传在开始上传之前会经过一轮文件扫描.

第一种做法是Plugin_Upload继承Upload, 然后重写它的start_upload方法.

用更轻的组合方式, 可以直接给原来的start_upload函数装饰上扫描功能, 甚至不需要衍生一个额外的子类.

(0)

相关推荐

  • Java中基于Aspectwerkz的AOP

      一.AOP编程概览 面向对象编程技术进入软件开发的主流对软件的开发方式产生了极大的影响,开发者可以用一组实体以及这些实体之间的关系将系统形象地表示出来,这使得他们能够设计出规模更大.更复杂的系统,开发周期也比以前更短.OO开发的唯一问题是,它本质上是静态的,需求的细微变化就可能对开发进度造成重大影响. Aspect-Oriented Programming(AOP)是对OO技术的补充和完善,它允许开发者动态地修改静态的OO模型,构造出一个能够不断增长以满足新增需求的系统,就象现实世界中的对象

  • 面向切面编程(AOP)的理解

    在传统的编写业务逻辑处理代码时,我们通常会习惯性地做几件事情:日志记录.事务控制及权限控制等,然后才是编写核心的业务逻辑处理代码.当代码编写完成回头再看时,不禁发现,扬扬洒洒上百行代码中,真正用于核心业务逻辑处理才那么几行,如图6-4所示.方法复方法,类复类,就这样子带着无可奈何遗憾地度过了多少个春秋.这倒也罢,倘若到了项目的尾声,突然决定在权限控制上需要进行大的变动时,成千上万个方法又得一一"登门拜访",痛苦"雪上加霜". 如果能把图6-4中众多方法中的所有共有代

  • javascript AOP 实现ajax回调函数使用比较方便

    复制代码 代码如下: function actsAsDecorator(object) { object.setupDecoratorFor = function(method) { if (! ('original_' + method in object) ) { object['original_' + method] = object[method]; object['before_' + method] = [ ]; object['after_' + method] = [ ]; o

  • MVC AOP面向切面编程简单介绍及实例

    MVC AOP面向切面编程 AOP这个词相信大家都没有接触太多过,但是实际上你们已经有所接触了,就在设计模式中.AOP所用的思想其实和设计模式是一样的,即在不修改原代码的情况下统一增加或者修改功能.还有,AOP大多用在spring里面,但是本文所写的只是在MVC中的应用,要注意. 一.简介 所谓AOP(Aspect Oriented Programming的缩写)意为面向切面的编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是

  • 实例讲解Java的Spring框架中的AOP实现

    简介 面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方式弥补了面向对象编程(OOP)的不足. 除了类(classes)以外,AOP提供了 切面.切面对关注点进行模块化,例如横切多个类型和对象的事务管理. (这些关注点术语通常称作 横切(crosscutting) 关注点.) Spring的一个关键的组件就是 AOP框架. 尽管如此,Spring IoC容器并不依赖于AOP,这意味着你可以自由选择是否使用AOP,AOP提供强大的中间件解决方案,这使得Spring IoC容器更加完善

  • 深入浅析Spring 的aop实现原理

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入封装.继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合.当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力.也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系.例如日志功能.日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无

  • java使用动态代理来实现AOP(日志记录)的实例代码

    下面是一个AOP实现的简单例子: 首先定义一些业务方法: 复制代码 代码如下: /** * Created with IntelliJ IDEA. * Author: wangjie  email:tiantian.china.2@gmail.com * Date: 13-9-23 * Time: 下午3:49 */public interface BussinessService {    public String login(String username, String password

  • C#开源的AOP框架--KingAOP基础

    AOP面向切面编程(Aspect Oriented Programming),是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.Spring框架用的核心技术就是AOP,是函数式编程的一种衍生范型.利用AOP的好处就是可以对业务逻辑进行隔离,降低耦合度,提高程序的可重用性,同时提高了开发的效率.开源的AOP也有不少,我这里用的KingAOP. 1 项目结构 2 定义一个日志记录的实体类User和LoggingAspect切面日志类 namespace AOPDemo.Logging

  • Java实现AOP面向切面编程的实例教程

    介绍 众所周知,AOP(面向切面编程)是Spring框架的特色功能之一.通过设置横切关注点(cross cutting concerns),AOP提供了极高的扩展性.那AOP在Spring中是怎样运作的呢?当你只能使用core java,却需要AOP技术时,这个问题的解答变得极为关键.不仅如此,在高级技术岗位的面试中,此类问题也常作为考题出现.这不,我的朋友最近参加了一个面试,就被问到了这样一个棘手的问题--如何在不使用Spring及相关库,只用core Java的条件下实现AOP.因此,我将在

  • 使用AOP改善javascript代码

    Aop又叫面向切面编程,用过spring的同学肯定对它非常熟悉,而在js中,AOP是一个被严重忽视的技术点,这篇就通过下面这几个小例子,来说说AOP在js中的妙用. 1, 防止window.onload被二次覆盖. 2,无侵入的统计代码. 3, 分离表单请求和校验. 4,给ajax请求动态添加参数. 5,职责链模式. 6, 组合代替继承. 先给出before和after这2个"切面"函数. 顾名思义,就是让一个函数在另一个函数之前或者之后执行,巧妙的是,before或者after都可以

  • 深入理解JavaScript系列(1) 编写高质量JavaScript代码的基本要点

    具体一点就是编写高质量JavaScript的一些要素,例如避免全局变量,使用单变量声明,在循环中预缓存length(长度),遵循代码阅读,以及更多. 此摘要也包括一些与代码不太相关的习惯,但对整体代码的创建息息相关,包括撰写API文档.执行同行评审以及运行JSLint.这些习惯和最佳做法可以帮助你写出更好的,更易于理解和维护的代码,这些代码在几个月或是几年之后再回过头看看也是会觉得很自豪的. 书写可维护的代码(Writing Maintainable Code ) 软件bug的修复是昂贵的,并且

  • 编写高质量JavaScript代码的基本要点

    才华横溢的Stoyan Stefanov,在他写的由O'Reilly初版的新书<JavaScript Patterns>(JavaScript模式)中,我想要是为我们的读者贡献其摘要,那会是件很美妙的事情.具体一点就是编写高质量JavaScript的一些要素,例如避免全局变量,使用单变量声明,在循环中预缓存length(长度),遵循代码阅读,以及更多. 此摘要也包括一些与代码不太相关的习惯,但对整体代码的创建息息相关,包括撰写API文档.执行同行评审以及运行JSLint.这些习惯和最佳做法可以

  • 5个书写JavaScript代码的坏习惯,看看你中枪了没?

    Javascript在互联网上名声很臭,但你又很难再找到一个像它这样如此动态.如此被广泛使用.如此根植于我们的生活中的另外一种语言.它的低学习门槛让很多人都称它为学前脚本语言,它另外一个让人嘲笑的东西是动态语言的概念是偏偏使用了高标准的静态数据类型.其实,你和Javascript都站错了立场,而现在,你让Javascript很生气.这里有五个原因能说明你的Javascript技术很烂. 1. 你没有使用命名空间. 是否还记得在大学里老师告诉你不要在家庭作业里使用全局变量?Javascript里的

  • 浅谈JavaScript 代码整洁之道

    概述 一张幽默的图片:软件质量通过你在阅读代码的时候有多少报怨来进行评估 Robert C. Martin 在 <代码整洁之道> 中提到的软件工程原则,同样适用于 JavaScript.这不是一个风格参考.它指导如何用 JavaScript 编写可读.可复用.可重构的软件. 并不是每一个原则都必须严格遵循,甚至很少得到大家的认同.它们仅用于参考,不过要知道这些原则都是<代码整洁之道>的作者们累积多年的集体经验. 我们在软件工程方面的技术发展刚刚超过 50 年,我们仍然在学习很多东西

  • 如何编写高质量 JavaScript 代码

    目录 一.易阅读的代码 1.统一代码格式 2.去除魔术数字 3.单一功能原则 二.高性能的代码 1.优化算法 2.使用内置方法 3.减少作用域链查找 4.避免做重复的代码 三.健壮性的代码 1.使用新语法 2.随时可扩展 3.避免副作用 4.整合逻辑关注点 前段时间有一个叫做"人类高质量男性"的视频火了,相信很多同学都刷到过.所以今天给大家分享下,什么叫做"人类高质量代码",哈哈,开个玩笑. 其实分享的都是一些自己平时总结的小技巧,算是抛砖引玉吧,希望能给大家带来一

  • 验证用户必选CheckBox控件与自定义验证javascript代码

    CheckBox控件,由于它的值是选择与非选择.因此在提交数据时,想让用户必须选择CheckBox,普通情况之下,不好做验证. 但我们可以使用asp:CustomValidator来验证,不过还得写自定义验证Javascript代码,可参考如下: 复制代码 代码如下: function ValidateCheckBox(sender, args) { var checkbox = document.getElementById("<%=CheckBox1.ClientID %>&qu

  • 一个即时表单验证的javascript代码

    可爱吧--教你做可爱女人--化妆 美容 美化 瘦身 护肤--深圳可爱吧 // 此脚本由刘海民编写 // 网站:http://www.szrgb.net // 邮箱:lovelium@gmail.com var num=5; var mon1=0; var mon2=0; var mon3=0; var mon4=0; var mon5=0; //封装得到对像ID涵数 function getObj(objName){return(document.getElementById(objName))

  • 纯JavaScript代码实现文本比较工具

    之前项目需求需要写一个纯js文本比较工具,在此小编把代码分享在我们平台供大家参考,算法有待优化,本文写的不好还请见谅. 先上效果图: 代码如下所示: 把源码保存为html格式的文件就可以直接运行了 <!doctype html> <html> <head> <title>文本比较工具</title> <style type="text/css"> *{padding:px;margin:px;} html,body

  • 不使用浏览器运行javascript代码的方法

    有时候我们想用js写一段小程序,但是又觉得使用浏览器去运行挺麻烦的,那么现在我们来看一下如何使用java程序调用javascript程序,这样就可以不借助浏览器就可执行js代码了. 之所以有这个需求是因为这几天在做的一个项目中碰到了这样的问题,我有一个javascript脚本,但是这个项目的其他代码都是用C\C++写的,不想将js代码转成C,感觉太麻烦了,所以就想如果可以在C下面直接调用javascript代码就好了,或者在shell中有一个可以不借助浏览器就可以直接运行js代码的工具也行.现在

随机推荐