轻松掌握JavaScript装饰者模式


Posted in Javascript onAugust 27, 2016

在传统的面向对象语言中,给对象添加功能常常使用继承的方式,但继承的方式会带来问题:当父类改变时,他的所有子类都将随之改变。 

当JavaScript脚本运行时,在一个对象中(或他的原型上)增加行为会影响该对象的所有实例, 

装饰者是一种实现继承的替代方案,它通过重载方法的形式添加新功能,该模式可以在被装饰者前面(before)或者后面(after)加上自己的行为以达到特定的目的。 

装饰者模式是为已有功能动态地添加更多功能的一种方式,把每个要装饰的功能放在单独的函数里,然后用该函数包装所要装饰的已有函数对象,因此,当需要执行特殊行为的时候,调用代码就可以根据需要有选择地、按顺序地使用装饰功能来包装对象。优点是把类(函数)的核心职责和装饰功能区分开了。 

我们可以定义工具函数,如下:

Function.prototype.before = function (beforeFn) {
  var self = this; //保存原函数的引用
  return function () { //返回包含了新函数和原函数的代理函数
    beforeFn.apply(this,arguments); //执行新函数,且保证this不被劫持
    return self.apply(this,arguments); //执行原函数,并返回原函数的执行结果,并保证this不被劫持
  }
};
Function.prototype.after = function (afterFn) {
  var self = this;
  return function () {
    var ret = self.apply(this,arguments);
    afterFn.apply(this,arguments);
    return ret;
  }
};

这里的参数beforeFn、afterFn即为要为原函数扩展新功能的新函数(添加装饰),它们的唯一区别是执行顺序的不同。如果不想污染Function的原型,可以用下面的方法:

var before = function (fn, beforeFn) {
  return function () {
    beforeFn.apply(this,arguments);
    return fn.apply(this,arguments);
  }
};
var after = function (fn, afterFn) {
  return function () {
    var ret = fn.apply(this,arguments);
    afterFn.apply(this,arguments);
    return ret;
  }
};

例子:给HTTP请求中带上一个参数防止CSRF攻击

var ajax = function (type, url, param) {
  console.log(param); //发送ajax请求代码略...
};
var beforeFn = function (type, url, param) {
  param.Token = 'Token';
};
ajax = ajax.before(beforeFn);
ajax('get','http://...com/userinfo',{name:'SuFa'});
//{ name: 'SuFa', Token: 'Token' }

通过给ajax函数动态装饰上Token参数,而不是直接在原函数上修改参数,保证了ajax函数仍然是一个纯净的函数,提高了它的可复用性,它可在无需做任何修改的情况下直接拿到别的项目中使用。 

例子:表单验证(把验证输入和表单提交的代码分离开来,然后动态的把验证输入功能装饰到表单提交之前,这样一来,我们就可以把验证输入部分写成一个插件的形式,用在不同的项目中)

//验证输入函数
var validata = function () {
  if(username.value === ''){
    alert('用户名不能为空');
    return false;
  }
  if(password.value === ''){
    alert('密码不能为空');
    return false;
  }
};
//表单提交函数
var formSubmit = function () {
  var param = {
    username: username.value,
    password: password.value
  };
  ajax('http://xxx.com/login',param);
};

formSubmit = formSubmit.before(validata);
submitBtn.onclick = function(){
  formSubmit();
};

参考文献: 《JavaScript模式》 《JavaScript设计模式与开发实践》

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery dialog open后,服务器端控件失效的快速解决方法
Dec 19 Javascript
js实现完美兼容各大浏览器的人民币大小写相互转换
Oct 29 Javascript
基于jquery实现轮播特效
Apr 22 Javascript
Jquery对新插入的节点 绑定Click事件失效的解决方法
Jun 02 Javascript
手机Web APP如何实现分享多平台功能
Aug 19 Javascript
AngularJS+bootstrap实现动态选择商品功能示例
May 17 Javascript
JScript实现地址选择功能
Aug 15 Javascript
element-ui 时间选择器限制范围的实现(随动)
Jan 09 Javascript
jQuery单页面文字搜索插件jquery.fullsearch.js的使用方法
Feb 04 jQuery
es6 super关键字的理解与应用实例分析
Feb 15 Javascript
vue+animation实现翻页动画
Jun 29 Javascript
js制作提示框插件
Dec 24 Javascript
node.js实现快速截图
Aug 27 #Javascript
购物车前端开发(jQuery和bootstrap3)
Aug 27 #Javascript
利用Angularjs和Bootstrap前端开发案例实战
Aug 27 #Javascript
轻松掌握JavaScript享元模式
Aug 27 #Javascript
JavaScript编码风格指南(中文版)
Aug 26 #Javascript
JavaScript使用forEach()与jQuery使用each遍历数组时return false 的区别
Aug 26 #Javascript
ES6中的数组扩展方法
Aug 26 #Javascript
You might like
Http 1.1 Etag 与 Last-Modified提高php效率
2008/01/10 PHP
PHP chmod 函数与批量修改文件目录权限
2010/05/10 PHP
C#使用PHP服务端的Web Service通信实例
2014/04/08 PHP
php获取图片信息的方法详解
2015/12/10 PHP
一个简单的php MVC留言本实例代码(必看篇)
2016/09/22 PHP
php判断文件上传图片格式的实例详解
2017/09/30 PHP
PHP7创建COOKIE和销毁COOKIE的实例方法
2020/02/03 PHP
一段效率很高的for循环语句使用方法
2007/08/13 Javascript
javascript 有趣而诡异的数组
2009/04/06 Javascript
javascript 清除输入框中的数据
2009/04/13 Javascript
form.submit()不能提交表单的错误原因及解决方法
2014/10/13 Javascript
在Node.js应用中使用Redis的方法简介
2015/06/24 Javascript
解决jquery中动态新增的元素节点无法触发事件问题的两种方法
2015/10/30 Javascript
Bootstrap字体图标无法正常显示的解决方法
2016/10/08 Javascript
详谈jQuery Ajax(load,post,get,ajax)的用法
2017/03/02 Javascript
详解RequireJS按需加载样式文件
2017/04/12 Javascript
H5基于iScroll实现下拉刷新和上拉加载更多
2017/07/18 Javascript
JS中图片压缩的方法小结
2017/11/14 Javascript
vue-cli 3.x 配置Axios(proxyTable)跨域代理方法
2018/09/19 Javascript
React中this丢失的四种解决方法
2019/03/12 Javascript
CountUp.js数字滚动插件使用方法详解
2019/10/17 Javascript
理解Proxy及使用Proxy实现vue数据双向绑定操作
2020/07/18 Javascript
python 3利用BeautifulSoup抓取div标签的方法示例
2017/05/28 Python
Python3实现爬取指定百度贴吧页面并保存页面数据生成本地文档的方法
2018/04/22 Python
Python中格式化字符串的四种实现
2020/05/26 Python
Selenium关闭INFO:CONSOLE提示的解决
2020/12/07 Python
实例教程 利用html5和css3打造一款创意404页面
2014/10/20 HTML / CSS
查询优化的一般准则有哪些
2015/03/08 面试题
大学生创业计划书的范文
2014/01/07 职场文书
旷课检讨书1000字
2014/02/14 职场文书
妇女工作先进事迹
2014/08/17 职场文书
会计师事务所实习证明
2014/11/16 职场文书
2015年高校保卫处工作总结
2015/07/23 职场文书
高中同学会致辞
2015/08/01 职场文书
Oracle 死锁的检测查询及处理
2021/09/25 Oracle
Vite + React从零开始搭建一个开源组件库
2022/06/25 Javascript