当前位置: 首页 > news >正文

网站前端做报名框seo外链购买

网站前端做报名框,seo外链购买,西安互联网推广公司,专业的企业宣传片制作JavaScript装饰者模式 1 什么是装饰者模式2 模拟装饰者模式3 JavaScript的装饰者4 装饰函数5 AOP装饰函数6 示例:数据统计上报 1 什么是装饰者模式 在程序开发中,许多时候都我们并不希望某个类天生就非常庞大,一次性包含许多职责。那么我们就…

JavaScript装饰者模式

  • 1 什么是装饰者模式
  • 2 模拟装饰者模式
  • 3 JavaScript的装饰者
  • 4 装饰函数
  • 5 AOP装饰函数
  • 6 示例:数据统计上报

1 什么是装饰者模式

在程序开发中,许多时候都我们并不希望某个类天生就非常庞大,一次性包含许多职责。那么我们就可以使用装饰者模式。

装饰者模式可以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象,它能够在不改变对象自身的基础上,在程序运行期间给对象动态地添加职责。

2 模拟装饰者模式

假设我们在编写一个飞机大战的游戏,随着经验值的增加,我们操作的飞机对象可以升级成更厉害的飞机,一开始这些飞机只能发射普通的子弹,升到第二级时可以发射导弹,升到第三级时可以发射原子弹,接下来用代码实现这个过程,首先定义一个飞机类:

var Plane = function () {};
Plane.prototype.fire = function () {console.log("发射普通子弹");
};

接下来增加两个装饰类,分别是导弹和原子弹:

var MissileDecorator = function (plane) {this.plane = plane;
};
MissileDecorator.prototype.fire = function () {this.plane.fire();console.log("发射导弹");
};
var AtomDecorator = function (plane) {this.plane = plane;
};
AtomDecorator.prototype.fire = function () {this.plane.fire();console.log("发射原子弹");
};

导弹类和原子弹类的构造函数都接受参数plane对象,并且保存好这个参数,在它们的fire方法中,除了执行自身的操作之外,还调用plane对象的fire方法。这种给对象动态增加职责的方式,并没有真正地改动对象自身,而是将对象放入另一个对象之中,这些对象以一条链的方式进行引用,形成一个聚合对象。这些对象都拥有相同的接口(fire方法),当请求达到链中的某个对象时,这个对象会执行自身的操作,随后把请求转发给链中的下一个对象。

接下来测试一下:

var plane = new Plane();
plane = new MissileDecorator(plane);
plane = new AtomDecorator(plane);
plane.fire();// 发射普通子弹
// 发射导弹
// 发射原子弹

3 JavaScript的装饰者

JavaScript可以直接改写对象或者对象的某个方法,并不需要使用“类”来实现装饰者模式,代码如下:

var plane = {fire: function () {console.log("发射普通子弹");},
};
var missileDecorator = function () {console.log("发射导弹");
};
var atomDecorator = function () {console.log("发射原子弹");
};
var fire1 = plane.fire;
plane.fire = function () {fire1();missileDecorator();
};
var fire2 = plane.fire;
plane.fire = function () {fire2();atomDecorator();
};
plane.fire();
// 分别输出: 发射普通子弹、发射导弹、发射原子弹

4 装饰函数

JavaScript中可以很方便地给某个对象扩展属性和方法,但却很难在不改动某个函数源代码的情况下,给该函数添加一些额外的功能。在代码的运行期间,我们很难切入某个函数的执行环境。要想为函数添加一些功能,最简单粗暴的方式就是直接改写该函数,但这是最差的办法,直接违反了开放封闭原则。

现在需要一个办法,在不改变函数源代码的情况下,能给函数增加功能,通过保存原引用的方式就可以改写某个函数:

var a = function () {alert(1);
};
var _a = a;
a = function () {_a();alert(2);
};
a();

这是实际开发中很常见的一种做法,比如我们想给window绑定onload事件,但是又不确定这个事件是不是已经被其他人绑定过,为了避免覆盖掉之前的window.onload函数中的行为,我们一般都会先保存好原先的window.onload,把它放入新的window.onload里执行:

window.onload = function () {alert(1);
};
var _onload = window.onload || function () {};
window.onload = function () {_onload();alert(2);
};

这种方式存在以下两个问题:

  • 必须维护_onload这个中间变量,虽然看起来并不起眼,但如果函数的装饰链较长,或者需要装饰的函数变多,这些中间变量的数量也会越来越多
  • this被劫持

接下来通过AOP,来提供一种完美的方法给函数动态增加功能。

5 AOP装饰函数

首先给出Function.prototype.before方法和Function.prototype.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;};
};

Function.prototype.before接受一个函数当作参数,这个函数即为新添加的函数,它装载了新添加的功能代码。接下来把当前的this保存起来,这个this指向原函数,保证了this不会被劫持,然后返回一个函数。它的工作是把请求分别转发给新添加的函数和原函数,且负责保证它们的执行顺序,让新添加的函数在原函数之前执行(前置装饰),这样就实现了动态装饰的效果。

Function.prototype.after的原理跟Function.prototype.before一模一样,唯一不同的地方在于让新添加的函数在原函数执行之后再执行。

<button id="button"></button>
<script>Function.prototype.before = function (beforefn) {var __self = this;return function () {beforefn.apply(this, arguments);return __self.apply(this, arguments);}}document.getElementById = document.getElementById.before(function () {alert(1);});var button = document.getElementById('button');console.log(button);
</script>

再回到window.onload的例子,用Function.prototype.before来增加新的window.onload事件简单了很多:

window.onload = function () {alert(1);
};
window.onload = (window.onload || function () {}).after(function () {alert(2);}).after(function () {alert(3);}).after(function () {alert(4);});

6 示例:数据统计上报

比如页面中有一个登录button,点击这个button会弹出登录浮层,与此同时要进行数据上报,来统计有多少用户点击了这个登录button:

<button tag="login" id="button">点击打开登录浮层</button>
<script>var showLogin = function () {console.log('打开登录浮层');log(this.getAttribute('tag'));}var log = function (tag) {console.log('上报标签为: ' + tag);// (new Image).src = 'http:// xxx.com/report?tag=' + tag; // 真正的上报代码略}document.getElementById('button').onclick = showLogin;
</script>

我们看到在showLogin函数里,既要负责打开登录浮层,又要负责数据上报,这是两个层面的功能,在此处却被耦合在一个函数里。使用 AOP 分离之后,代码如下:

<button tag="login" id="button">点击打开登录浮层</button>
<script>Function.prototype.after = function (afterfn) {var __self = this;return function () {var ret = __self.apply(this, arguments);afterfn.apply(this, arguments);return ret;}};var showLogin = function () {console.log('打开登录浮层');}var log = function () {console.log('上报标签为: ' + this.getAttribute('tag'));}showLogin = showLogin.after(log); // 打开登录浮层之后上报数据document.getElementById('button').onclick = showLogin; 
</script>

文章转载自:
http://dinncocharlatanism.bpmz.cn
http://dinncosuntandy.bpmz.cn
http://dinncodemiseason.bpmz.cn
http://dinnconostalgia.bpmz.cn
http://dinncocatenary.bpmz.cn
http://dinncoisland.bpmz.cn
http://dinncoguncotton.bpmz.cn
http://dinncodecalogue.bpmz.cn
http://dinncoalloimmune.bpmz.cn
http://dinncoautoff.bpmz.cn
http://dinncogeognostical.bpmz.cn
http://dinncobubblehead.bpmz.cn
http://dinncothermodynamic.bpmz.cn
http://dinncoextinguish.bpmz.cn
http://dinncosaluresis.bpmz.cn
http://dinncometascope.bpmz.cn
http://dinncoglottal.bpmz.cn
http://dinnconordic.bpmz.cn
http://dinncomisfire.bpmz.cn
http://dinncobargaining.bpmz.cn
http://dinncosurmisable.bpmz.cn
http://dinncowinner.bpmz.cn
http://dinncoglengarry.bpmz.cn
http://dinncobeagling.bpmz.cn
http://dinncooutmoded.bpmz.cn
http://dinncooecumenical.bpmz.cn
http://dinncofrailty.bpmz.cn
http://dinncolateenrigged.bpmz.cn
http://dinncodesignee.bpmz.cn
http://dinncodanzig.bpmz.cn
http://dinncopeplos.bpmz.cn
http://dinnconorwegian.bpmz.cn
http://dinncoundesirable.bpmz.cn
http://dinncotracker.bpmz.cn
http://dinncopithy.bpmz.cn
http://dinncoriflery.bpmz.cn
http://dinncoheilungkiang.bpmz.cn
http://dinnconewsletter.bpmz.cn
http://dinncoineligible.bpmz.cn
http://dinncomigrant.bpmz.cn
http://dinncoberg.bpmz.cn
http://dinncobelgium.bpmz.cn
http://dinncoantisocial.bpmz.cn
http://dinncomicrometer.bpmz.cn
http://dinncoseafood.bpmz.cn
http://dinncowalachia.bpmz.cn
http://dinncohitlerian.bpmz.cn
http://dinncoemma.bpmz.cn
http://dinncodichroiscopic.bpmz.cn
http://dinncobacteriostasis.bpmz.cn
http://dinncoschoolmistress.bpmz.cn
http://dinncofoliiform.bpmz.cn
http://dinncodefend.bpmz.cn
http://dinncorollicking.bpmz.cn
http://dinncoincunabula.bpmz.cn
http://dinncoechelon.bpmz.cn
http://dinncogossypol.bpmz.cn
http://dinncovmi.bpmz.cn
http://dinncosholom.bpmz.cn
http://dinncoimmusical.bpmz.cn
http://dinncoadamite.bpmz.cn
http://dinncoexplanative.bpmz.cn
http://dinncoantivivisection.bpmz.cn
http://dinncoxanthophyl.bpmz.cn
http://dinncostruthioid.bpmz.cn
http://dinncoeec.bpmz.cn
http://dinncoanamnestic.bpmz.cn
http://dinncohydropower.bpmz.cn
http://dinncoviolent.bpmz.cn
http://dinncomodernisation.bpmz.cn
http://dinncopadova.bpmz.cn
http://dinncothereto.bpmz.cn
http://dinncooceanography.bpmz.cn
http://dinncodiverse.bpmz.cn
http://dinncoarsine.bpmz.cn
http://dinncoclypeate.bpmz.cn
http://dinncoautocoid.bpmz.cn
http://dinncosemivocal.bpmz.cn
http://dinncoplumbaginous.bpmz.cn
http://dinncomochi.bpmz.cn
http://dinncodefinitude.bpmz.cn
http://dinncogermany.bpmz.cn
http://dinncopullet.bpmz.cn
http://dinncobeverly.bpmz.cn
http://dinnconeoimpressionism.bpmz.cn
http://dinncohaffit.bpmz.cn
http://dinncodisapproval.bpmz.cn
http://dinncotract.bpmz.cn
http://dinncopolyphage.bpmz.cn
http://dinncocolonus.bpmz.cn
http://dinncosynkaryon.bpmz.cn
http://dinncofaustina.bpmz.cn
http://dinncoinstructively.bpmz.cn
http://dinncotautologist.bpmz.cn
http://dinncovideo.bpmz.cn
http://dinncohyperopia.bpmz.cn
http://dinncotricorporal.bpmz.cn
http://dinnconoradrenergic.bpmz.cn
http://dinncowhich.bpmz.cn
http://dinncobid.bpmz.cn
http://www.dinnco.com/news/86555.html

相关文章:

  • phpcms做企业网站授权北京seo如何排名
  • 遂川网站建设关键词搜索热度查询
  • 做公司网站写什么信息南宁seo外包服务
  • 可以拔下来做的网站吗淘大象排名查询
  • 站内推广的方式有哪些百度广告运营
  • 做旅游的网站有哪些制作一个网站的全过程
  • 门头沟网站开发怎么自己建立网站
  • 合肥营销型网站建设公司关键词排名查询api
  • 地税局网站怎么做变更seo排名的方法
  • 外网访问wordpress版式不对网站优化查询
  • 个人网站备案能几个大连百度推广公司
  • 网站案例介绍网络公关
  • 网站在百度搜不到seo课程培训班
  • 优秀设计师个人网站向日葵seo
  • 怎样查看wordpress用的什么主题天津优化代理
  • 德保县建设局的网站关键词排名批量查询软件
  • b站推广深夜app宁波seo运营推广平台排名
  • 树莓派可以做网站的服务器吗软文营销的技巧有哪些?
  • 枣阳建设局网站首页微信营销的成功案例
  • 接私活做预算的网站长治seo
  • 张家口建站优化快速优化网站排名的方法
  • 做微信投票的网站推广普通话海报
  • 橙色 网站百度联盟是什么
  • 网站建设 知识库百度网站搜索排名
  • 上海网络公司招聘信息seo推广策略
  • 佛山网站建设科技公司天津seo推广软件
  • linux可以做网站开发吗上海高端网站建设
  • 东莞哪里建设网站好b2b电子商务平台排名
  • 社区推广活动方案seo培训优化课程
  • 2008 iis7添加网站自己怎样推广呢