学习JavaScript设计模式之装饰者模式
作者:奋飛 发布时间:2023-07-19 08:59:07
有时我们不希望某个类天生就非常庞大,一次性包含许多职责。那么我们就可以使用装饰着模式。
装饰着模式可以动态地给某个对象添加一些额外的职责,从而不影响这个类中派生的其他对象。
装饰着模式将一个对象嵌入另一个对象之中,实际上相当于这个对象被另一个对象包装起来,形成一条包装链。
一、不改动原函数的情况下,给该函数添加些额外的功能
1. 保存原引用
window.onload = function() {
console.log(1);
};
var _onload = window.onload || function() {};
window.onload = function() {
_onload();
console.log(2);
}
问题:
(1)必须维护中间变量
(2)可能遇到this被劫持问题
在window.onload的例子中没有这个烦恼,是因为调用普通函数_onload时,this也指向window,跟调用window.onload时一样。
2. this被劫持:
var _getElementById = document.getElementById;
document.getElementById = function(id) {
console.log(1);
return _getElementById(id);
}
return _getElementById(id); // 报错“Uncaught TypeError: Illegal invocation”
因为_getElementById是全局函数,当调用全局函数时,this是指向window的,而document.getElementById中this预期指向document。
3. 解决this被劫持:
var _getElementById = document.getElementById;
document.getElementById = function(id) {
console.log(1);
return _getElementById.call(document, id);
}
二、用AOP装饰函数
/* 让新添加的函数在原函数之前执行(前置装饰)*/
Function.prototype.before = function(beforefn) {
var _self = this;
return function() {
beforefn.apply(this, arguments); // 新函数接收的参数会被原封不动的传入原函数
return _self.apply(this, arguments);
};
};
/* 让新添加的函数在原函数之后执行(后置装饰)*/
Function.prototype.after = function(afterfn) {
var _self = this;
return function() {
var ret = _self.apply(this, arguments);
afterfn.apply(this, arguments);
return ret;
};
};
document.getElementById = document.getElementById.before(function() {
console.log(1);
});
三、避免污染原型
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;
};
};
document.getElementById = before(document.getElementById, function(){
console.log(1);
});
四、示例–插件式的表单验证
结合《学习JavaScript设计模式之策略模式》中的【表单验证】,运用到ajax提交数据验证,效果很棒!
修改上述before方法
var before = function(fn, beforefn) {
return function() {
if(beforefn.apply(this, arguments) === false) {
// beforefn返回false,直接return,不执行后面的原函数
return;
}
return fn.apply(this, arguments);
};
};
/* 模拟数据验证*/
var validate = function() {
if(username === "") {
console.log("验证失败!");
return false;
}
return true;
}
/* 模拟ajax提交*/
var formSubmit = function() {
console.log("提交!!!");
}
username = 1;
formSubmit = before(formSubmit, validate); // 提交!!!
formSubmit();
username = "";
formSubmit = before(formSubmit, validate); // 验证失败!
formSubmit();
五、装饰者模式和代理模式
相同点:这两种模式都描述了怎么为对象提供一定程度上的间接引用,它们的实现部分都保留了对另外一个对象的引用,并且向那个对象发送请求。
区别:
(1)代理模式:当直接访问本地不方便或者不符合需求时,为这个本体提供一个替代者。本地定义关键功能,而代理提供或拒绝对它的访问,或者在访问本体之前走一些额外的事情。(其做的事情还是跟本体一样)
(2)装饰者模式:为对象动态加入行为。(一开始不能确定对象的全部功能,实实在在的为对象添加新的职责和行为)
希望本文所述对大家学习javascript程序设计有所帮助。
猜你喜欢
- 先把这个script加到你的页面里:http://code.google.com/p/doufu/source/browse/trunk/n
- 希望对您有所帮助!推荐:[精品]ASP中常用的22个FSO文件操作函数 <%@ Language=VBScript
- function GetRequest() { var
- 代码如下:--创建测试表 DECLARE @Users TABLE ( ID INT IDENTITY(1,1), UserIn
- ASP中给函数传参确实是个麻烦事,当参数个数特别多的时候(比如有七八个或者更多的参数个数)差不多就要眼冒金星了,一个个的数吧。而且要命的是参
- 最好也是最简单的办法就是利用Cookie,而不必用到数据库。当然,你愿意用数据库也可以。下面就是利用Cookie来实现的:< 
- js运行效果,含公历农历,生肖及节日的javascript日历代码:<html><head><meta htt
- 让你的读者能够方便地收藏你的文章到社会化书签(网摘)网站,如 新浪,google,yahoo,Del.icio.us, 365key等添加到
- 以图像处理见长的微软Live实验室,最近发布了一款新作:Pivot。装完启动后的第一印象就是一款浏览器,和IE、FF、Chrome又不太一样
- 又发现一个IE不标准的地方,unshift方法会返回新数组的长度,但IE6与IE7则返回undefined。var a = [3,2,1,4
- 主要讲 except 和 not in 的性能上的区别。 代码如下:CREATE TABLE tb1(ID int) CREAT
- QueryCache(下面简称QC)是根据SQL语句来cache的。一个SQL查询如果以select开头,那么MySQL服务器将尝试对其使
- 原文地址:30 Days of Mootools 1.2 Tutorials - Day 14 - Periodical and Intro
- IP字段截取,判断访问者ip,根据ip来显示不同图片,很简单的程序<%ip=request.servervariables("
- 收集和分发数据是网络管理的职责之一,而且必须确保这些数据的准确性和安全性。不管它们是什么操作系统,数据库服务器需要特殊的管理以保证操作上的安
- 数据库是数据的集合,与数学的集合论有密不可分的关系。为提高查询速度,我们可以:对数据表添加索引,以加快搜索速度;通过编程技巧最大限度地利用索
- 周六。据闻北服美女甚多,于是应邀去做了一个关于UED的讲座。人不多,讲的很乱,但大家听的很认真,欣慰。讲完之后回答了很多关于社区、搜索、设计
- JavaScript组件打包模式js组件通常带着css image ,但这样使用起来可能会有些小麻烦,为了让组件足够的solo,有了把css
- 阅读上一篇:网马解密大讲堂——网马解密初级篇今天主要讲解的内容是Freshow工具的使用方法,工欲善其事,必先利其器,首先要学会如何使用解密
- sql server 全文检索有两种搜索方式,一种是contains,另一种是freetext。前者是包含,类似于 like '%关