使用AOP改善javascript代码


Posted in Javascript onMay 01, 2015

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

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

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

使用AOP改善javascript代码

处理window.onload被二次覆盖.

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

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

使用AOP改善javascript代码

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

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

使用AOP改善javascript代码

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

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

使用AOP改善javascript代码

无侵入的统计代码

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

使用AOP改善javascript代码

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

使用AOP改善javascript代码

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

使用AOP改善javascript代码

分离表单请求和校验

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

使用AOP改善javascript代码

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

使用AOP改善javascript代码

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

使用AOP改善javascript代码

过最前面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请求的代理函数.使用AOP改善javascript代码

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

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

使用AOP改善javascript代码

开始发送请求:

使用AOP改善javascript代码

职责链模式.

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

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

使用AOP改善javascript代码

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

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

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

使用AOP改善javascript代码

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

使用AOP改善javascript代码

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

使用AOP改善javascript代码

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

使用AOP改善javascript代码

组合代替继承

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

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

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

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

使用AOP改善javascript代码

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

使用AOP改善javascript代码

Javascript 相关文章推荐
showModelessDialog()使用详解
Sep 07 Javascript
javascript 面向对象编程基础:继承
Aug 21 Javascript
jquery 层次选择器siblings与nextAll的区别介绍
Aug 02 Javascript
JQuery对class属性的操作实现按钮开关效果
Oct 11 Javascript
jquery组件使用中遇到的问题整理及解决
Feb 21 Javascript
javascript生成随机颜色示例代码
May 05 Javascript
JS实现漂亮的淡蓝色滑动门效果代码
Sep 23 Javascript
angularjs在ng-repeat中使用ng-model遇到的问题
Jan 21 Javascript
jQuery实现元素拖拽并cookie保存顺序的方法
Feb 20 Javascript
Vuejs 实现简易 todoList 功能 与 组件实例代码
Sep 10 Javascript
原生小程序封装跑马灯效果
Oct 21 Javascript
vue3+typescript实现图片懒加载插件
Oct 26 Javascript
Javascript aop(面向切面编程)之around(环绕)分析
May 01 #Javascript
jQuery插件Zclip实现完美兼容个浏览器点击复制内容到剪贴板
Apr 30 #Javascript
jQuery插件slider实现拖动滑块选取价格范围
Apr 30 #Javascript
javascript实现验证身份证号的有效性并提示
Apr 30 #Javascript
PHP+jQuery实现随意拖动层并即时保存拖动位置
Apr 30 #Javascript
jquery实现键盘左右翻页特效
Apr 30 #Javascript
jquery Validation表单验证使用详解
Sep 12 #Javascript
You might like
星际实力自我测试
2020/03/04 星际争霸
PHP获取本周第一天和最后一天示例代码
2014/02/24 PHP
php反射应用示例
2014/02/25 PHP
PHP抓取远程图片(含不带后缀的)教程详解
2016/10/21 PHP
docker-compose部署php项目实例详解
2019/07/30 PHP
解决PHP使用CURL发送GET请求时传递参数的问题
2019/10/11 PHP
让人印象深刻的10个jQuery手风琴效果应用
2012/05/08 Javascript
JavaScript实现鼠标滑过处生成气泡的方法
2015/05/16 Javascript
表单验证正则表达式实例代码详解
2015/11/09 Javascript
jQuery中事件与动画的总结分享
2016/05/24 Javascript
JSONP基础知识详解
2017/03/19 Javascript
微信小程序开发的基本流程步骤
2019/01/31 Javascript
vue cli 3.0 搭建项目的图文教程
2019/05/17 Javascript
JavaScript中的ES6 Proxy的具体使用
2019/06/16 Javascript
layui表格分页 记录勾选的实例
2019/09/02 Javascript
原生JS与CSS实现软件卸载对话框功能
2019/12/05 Javascript
vue实现公共方法抽离
2020/07/31 Javascript
浅谈python正则的常用方法 覆盖范围70%以上
2018/03/14 Python
Django视图扩展类知识点详解
2019/10/25 Python
Python collections中的双向队列deque简单介绍详解
2019/11/04 Python
css3发光搜索表单分享
2014/04/11 HTML / CSS
微软俄罗斯官方网站:Microsoft俄罗斯
2016/09/18 全球购物
马来西亚最好的婴儿商店:Motherhood
2017/09/14 全球购物
意大利领先的线上奢侈品销售电商:Eleonora Bonucci
2017/10/17 全球购物
Bose法国官网:购买耳机、扬声器、家庭影院、专业音响
2017/12/21 全球购物
如何估计一张表的大小(假设该表中有1万条数据)
2016/03/27 面试题
什么是servlet链?
2014/07/13 面试题
品学兼优的大学生自我评价
2013/09/20 职场文书
担保书怎么写
2014/04/01 职场文书
销售团队口号大全
2014/06/06 职场文书
植物生产学专业求职信
2014/08/08 职场文书
我的大学四年规划书范文2014
2014/09/26 职场文书
2014幼儿园小班工作总结
2014/11/10 职场文书
文体活动总结
2015/02/04 职场文书
求职简历自我评价2015
2015/03/10 职场文书
护士岗前培训心得体会
2016/01/08 职场文书