JS设计模式之装饰器模式

本文详细解释了装饰器模式在JavaScript中的应用,展示了如何在运行时为对象动态添加功能,以及call、bind和apply在控制函数上下文中的作用。通过实例演示了如何使用装饰器模式为函数添加前置和后置方法,提高代码的灵活性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义:

装饰器模式(Decorator Pattern)是一种结构型设计模式,用于在不改变原有对象的基础上,动态地给对象添加功能或职责。它通过在运行时包装对象来增加新的行为,从而提供了一种灵活的方式来扩展对象的功能。

装饰器模式包括两种主要角色:被装饰者(Component)和装饰者(Decorator)。被装饰者是一个接口或抽象类,定义了可以添加装饰的对象的接口。装饰者则实现了与被装饰者相同的接口,并持有一个指向被装饰者的引用。装饰者可以在其方法中调用被装饰者的方法,从而在被装饰者的行为之前或之后添加新的行为。

装饰器模式的优点包括:

  1. 动态扩展:可以在运行时动态地为对象添加功能,而无需修改其类定义。
  2. 灵活性:可以根据需要组合多个装饰器来创建具有不同行为的对象。
  3. 透明性:对于使用装饰器模式的客户端来说,被装饰者和装饰者对象都是一致的,因此它们可以无缝地替换彼此。

装饰器模式在多种场景下都非常有用,例如:

  1. 当需要动态地为一个对象添加功能时,可以使用装饰器模式来扩展其功能。
  2. 当需要以不同的方式组合对象的功能时,装饰器模式可以提供灵活的解决方案。
  3. 当需要对对象进行透明的包装以提供额外的功能或修改其行为时,可以使用装饰器模式

1.JS中如何动态的为一个对象添加功能

1.1定义函数前置方法和后置方法

前置:

这里可以看到,我在Function构造函数上添加了一个原型方法,名字叫before,当我想为我现在的函数或者某个对象添加功能的时候,就传入一个beforeFn,这个函数是我想向对象添加功能,并且在原函数执行之前执行的函数,var _this = this,这里是要保证我们函数this的指向和原函数要保持一致,举个例子:

在这个图片里面,ceshi函数this原本是指向window的,当我给他绑定到inp上的时候,function谁调用指向那个对象,此时ceshi输出的this就是input这个dom元素,同理,假如我有一个按钮,正常这个按钮的功能是当我点击他的时候,进行一个页面的跳转,但是现在我想给这个按钮加一个功能,就是让它跳转前,去上传一些数据。此时很多人都会在button这个按钮绑定的事件函数中去添加代码去实现这个效果,但是如果一个项目中有20,30或者更多的按钮需要加这个功能呢,一个一个添加的话,增加代码并且可读性变差,此时,我们就可以用装饰器模式,为这个按钮所绑定的函数加一个功能。

DOM:

js:

初学者看这里可能已经有点懵了,但是细细研读我写的解释,其实还是很好理解的,首先我没获取dom,是因为id可以作为dom去直接使用onclik绑定事件,接着,原先我的按钮,当我点击的时候,它只会执行render()这个函数,这个函数的功能是做一些页面处理逻辑,例如跳转页面,但是我现在有一个新的需求,想在跳转页面前执行一个log函数,这个函数的功能是提交一些数据,此时我就写了render = render.before(log),我们来读一下,点击按钮时触发render()函数,原本只会输出页面处理逻辑,但是在执行之前我给render做了一个重新赋值,让它等于render.before(log),此时我们就调用了Function这个原型的before方法,接着render.before(log)其实就等价于 

beforeFn,就是我们的log方法,本来log方法的指向时windows,现在通过apply改变了log方法的指向,让它指向了button,同时还执行了log函数,如果这里不理解的可以去看看call,bind,apply的区别:

call、bind和apply之间的主要区别体现在以下三个方面:

  1. 执行方式
  • call和apply是改变后页面加载之后就立即执行,是同步代码。
  • bind是异步代码,改变后不会立即执行,而是返回一个新的函数。
  1. 传参方式
  • call和bind可以接受多个参数,除了一个是this指向外,其余的参数对应函数的参数。
  • apply只接受两个参数,第一个参数是this的指向,第二个参数是一个数组或者类数组对象,其中的数组元素将作为单独的参数传给函数。
  1. 修改this的性质
  • call和apply直接修改了函数的this上下文。
  • bind返回一个新的函数,这个函数的this被永久地绑定到了bind的第一个参数。如果这个新函数作为构造函数被调用,那么this不再指向传入bind()的第一个参数,而是指向新生成的对象。

在JavaScript中,这些函数方法常常用于控制函数执行时的上下文(即this的值),使得函数可以按照我们期望的方式操作特定的对象。它们都是Function.prototype上的方法,因此所有的函数都可以使用它们。

所以在这里,我们的log函数就已经执行了,并且最后return了_this.apply(this.arguments),_this=this前面我们就已经把它缓存起来了,_this指向的是原来的函数,也就是原来的render

而现在的this,就变成了windows对象了,因为是在windows对象里用的function,return _this.apply(this.arguments),这里其实做了两步,第一步,首先把原函数给执行了,并且把原函数的this,指向了window。第二步返回原函数的返回值,这里我们是没有返回值的,如果说在原来的render函数中加上return 11111,然后在最后调用的时候输出console.log(render()),就能拿到11111

所以整体执行顺序为,在点击之前,我们使用装饰器模式给render添加了新功能,log,当我们点击按钮的时候,其实触发的函数,就是新的render.

同理,如果要在原来的render函数后面加功能,可以这么写:

总结:js的基础很重要,不然的话接触设计模式,确实很难懂,先把基础看会了,再来接触设计模式,能得到更好的效果,以上就是js设计模式之装饰器模式的用法和案例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值