这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
这篇文章主要帮助大家轻松掌握 JavaScript 装饰者模式,告诉大家什么是 js 装饰者模式,感兴趣的小伙伴们可以参考一下
在传统的面向对象语言中,给对象添加功能常常使用继承的方式,但继承的方式会带来问题:当父类改变时,他的所有子类都将随之改变。
当 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 设计模式与开发实践》
来源: http://www.phperz.com/article/17/0519/332287.html