轻松掌握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 相关文章推荐
fromCharCode和charCodeAt 方法
Dec 27 Javascript
基于jquery的放大镜效果
May 30 Javascript
获取元素距离浏览器周边的位置的方法getBoundingClientRect
Apr 17 Javascript
jQuery中:last-child选择器用法实例
Dec 31 Javascript
JavaScript中神奇的call()方法
Mar 12 Javascript
Angularjs实现多图片上传预览功能
Jul 18 Javascript
react在安卓中输入框被手机键盘遮挡问题的解决方法
Sep 03 Javascript
fetch 如何实现请求数据
Dec 20 Javascript
详解webpack打包vue项目之后生成的dist文件该怎么启动运行
Sep 06 Javascript
vue过滤器实现日期格式化的案例分析
Jul 02 Javascript
jQuery+ajax实现用户登录验证
Sep 13 jQuery
微信小程序实现自定义动画弹框/提示框的方法实例
Nov 06 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版本号
2006/10/09 PHP
php中使用addslashes函数报错问题的解决方法
2013/02/06 PHP
windows7下安装php的php-ssh2扩展教程
2014/07/04 PHP
PHP高级编程实例:编写守护进程
2014/09/02 PHP
详解PHP的Yii框架中扩展的安装与使用
2016/04/01 PHP
PHP使用HTML5 FormData对象提交表单操作示例
2019/07/02 PHP
25个好玩的JavaScript小游戏分享
2011/04/22 Javascript
关于 文本框默认值 的操作js代码
2012/01/12 Javascript
JavaScript中的null和undefined解析
2012/04/14 Javascript
nodejs的require模块(文件模块/核心模块)及路径介绍
2013/01/14 NodeJs
对new functionName()定义一个函数的理解
2014/05/22 Javascript
非常漂亮的相册集 使用jquery制作相册集
2016/04/28 Javascript
AngularJS中如何使用echart插件示例详解
2016/10/26 Javascript
Bootstrap栅格系统使用方法及页面调整变形的解决方法
2017/03/10 Javascript
js自定义弹框插件的封装
2020/08/24 Javascript
jQuery图片查看插件Magnify开发详解
2017/12/25 jQuery
深入理解nodejs搭建静态服务器(实现命令行)
2019/02/05 NodeJs
详解vue使用插槽分发内容slot的用法
2019/03/28 Javascript
小程序登录/注册页面设计的实现代码
2019/05/24 Javascript
Python 文件处理注意事项总结
2017/04/10 Python
Python中easy_install 和 pip 的安装及使用
2017/06/05 Python
Python如何调用外部系统命令
2019/08/07 Python
使用python修改文件并立即写回到原始位置操作(inplace读写)
2020/06/28 Python
手对手的教你用canvas画一个简单的海报的方法示例
2018/12/10 HTML / CSS
德国鞋子网上商店:Omoda.de
2017/03/31 全球购物
斯洛伐克家具和时尚装饰品购物网站:Butlers.sk
2019/09/08 全球购物
C语言怎样定义和声明全局变量和函数最好
2013/11/26 面试题
管理科学大学生求职信
2013/11/13 职场文书
美术指导求职信
2014/03/17 职场文书
捐款活动总结
2014/08/27 职场文书
开除通知书范本
2015/04/25 职场文书
正规借条模板
2015/05/26 职场文书
春节晚会开场白
2015/05/29 职场文书
读后感怎么写?书写读后感的基本技巧!
2019/12/10 职场文书
解决pytorch 损失函数中输入输出不匹配的问题
2021/06/05 Python
浅谈redis的过期时间设置和过期删除机制
2022/03/18 MySQL