轻松掌握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 相关文章推荐
js常用函数 不错
Sep 08 Javascript
javascript 文章截取部分无损html显示实现代码
May 04 Javascript
JS+CSS制作DIV层可(最小化/拖拽/排序)功能实现代码
Feb 25 Javascript
node.js中的fs.fstatSync方法使用说明
Dec 15 Javascript
详解js中构造流程图的核心技术JsPlumb
Dec 08 Javascript
分步解析JavaScript实现tab选项卡自动切换功能
Jan 25 Javascript
AngularJS表单验证中级篇(3)
Sep 28 Javascript
BootStrap 图标icon符号图标glyphicons不正常显示的快速解决办法
Dec 08 Javascript
微信小程序本作用域下调用全局JS详解及实例
Feb 22 Javascript
ES6中Array.includes()函数的用法
Sep 20 Javascript
vue使用xe-utils函数库的具体方法
Mar 06 Javascript
CSS3 动画卡顿性能优化的完美解决方案
Sep 20 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
PHP 面向对象程序设计(oop)学习笔记 (二) - 静态变量的属性和方法及延迟绑定
2014/06/12 PHP
Yii遍历行下每列数据的方法
2016/10/17 PHP
jQuery 行背景颜色的交替显示(隔行变色)实现代码
2009/12/13 Javascript
Js获取下拉框选定项的值和文本的实现代码
2014/02/26 Javascript
JS实现一个列表中包含上移下移删除等功能
2014/09/24 Javascript
JavaScript编写带旋转+线条干扰的验证码脚本实例
2016/05/30 Javascript
webpack开发跨域问题解决办法
2017/08/03 Javascript
nodejs实现截取上传视频中一帧作为预览图片
2017/12/10 NodeJs
详解最新vue-cli 2.9.1的webpack存在问题
2017/12/16 Javascript
Vue.js组件间的循环引用方法示例
2017/12/27 Javascript
jquery写出PC端轮播图实例
2018/01/26 jQuery
vue 弹窗时 监听手机返回键关闭弹窗功能(页面不跳转)
2019/05/10 Javascript
layui 弹出层值回传解决方式
2019/11/14 Javascript
JavaScript图像放大镜效果实现方法详解
2020/06/28 Javascript
详解python调度框架APScheduler使用
2017/03/28 Python
python机器学习之神经网络(三)
2017/12/20 Python
python3解析库lxml的安装与基本使用
2018/06/27 Python
浅谈Python的方法解析顺序(MRO)
2020/03/05 Python
python实现单张图像拼接与批量图片拼接
2020/03/23 Python
Python实现将元组中的元素作为参数传入函数的操作
2020/06/05 Python
Python:__eq__和__str__函数的使用示例
2020/09/26 Python
css3实现顶部社会化分享按钮示例
2014/05/06 HTML / CSS
HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题
2021/01/19 HTML / CSS
英国最受欢迎的在线隐形眼镜商店:VisionDirect.co.uk
2018/12/06 全球购物
欧洲领先的火车票和大巴票预订平台:Trainline
2018/12/26 全球购物
必须要使用游标的SQL语句有那些
2012/05/07 面试题
阿德的梦教学反思
2014/02/06 职场文书
财务总经理岗位职责
2014/02/16 职场文书
工作目标责任书
2014/07/23 职场文书
励志演讲稿3分钟
2014/08/21 职场文书
个人对照检查材料思想汇报(四风问题)
2014/09/25 职场文书
责任书格式
2015/01/29 职场文书
银行招聘自荐信
2015/03/06 职场文书
高三教师工作总结2015
2015/07/21 职场文书
MySQL索引篇之千万级数据实战测试
2021/04/05 MySQL
纯html+css实现Element loading效果
2021/08/02 HTML / CSS