这是我参与更文挑战的第14
天,活动详情查看:更文挑战
装饰者模式常见用法
装饰者模式也可以叫做包装器(wrapper)。
场景:我们需要去更改一个很复杂的函数,给这个函数添加一些额外的功能。但是这个函数中包含了很多复杂逻辑。一般情况下,我们最好是不去动内部函数的逻辑。
在函数外部去进行更改和编写。我们可以通过保存原引用的方式来改写这个函数:
let a = function() {
alert(1);
}
let _a = a;
a = function() {
_a();
alert(2);
}
a();
复制代码
这是实际开发中很常见的一种做法,比如我们想给window绑定onload事件,但是不知道之前有没有绑定过。所以我们需要在原有的onload上新增。我们在很多app生命周期中都会用到。
window.onload = function() {
alert(1);
}
let _onload = window.onload || function() {};
window.onload = function() {
_onload();
alert(2);
}
复制代码
用AOP装饰函数
实际上,这种方式也会改变this的指向,如果想不改变this指向,我们在调用原有的函数时需要绑定this。
如果要实现通用这种装饰器,我们可以引入AOP来实现,并绑定this指向。
// 在原函数之前执行
Function.prototype.before = function(beforeFn) {
let _self = this; // 保存原函数引用
return function() {
beforeFn.apply(this, arguments); // 执行新函数,绑定this
return _self.apply(this, arguments); // 执行原函数,并返回原函数执行结果
}
}
// 在原函数之后执行
Function.prototype.after = function(afterFn) {
let _self = this;
return function() {
let func = _self.apply(this, arguments);
afterFn.apply(this, arguments);
return func;
}
}
复制代码
这样封装过后来看一下,我们该怎么使用。还是之前的例子:
window.onload = function() {
alert(2);
}
// 原函数之前
window.onload = (window.onload || function() {}).before(function() {
alert(1);
});
// 原函数之后
window.onload = (window.onload || function() {}).after(function() {
alert(3);
alert(4);
});
复制代码
利用装饰者模式也可以改造我们的表单提交方式,让其看起来更简洁,函数功能也可以保持相对干净。
// 在原函数之前执行
Function.prototype.before = function(beforeFn) {
let _self = this; // 保存原函数引用
return function() {
if(beforeFn.apply(this, arguments) === false) { // 根据validataFunc返回的校验结果,执行函数
return;
}
return _self.apply(this, arguments); // 执行原函数,并返回原函数执行结果
}
}
const validataFunc = function() {
if(name.value === '') {
alert('用户名不能为空');
return false;
}
if(pwd.value === '') {
alert('密码不能为空');
return false;
}
}
const submitForm = function() {
const {
name: name.value,
pwd: pwd.value
}
ajax(opts, (data) => {
console.log('success')
}, (err) => {
console.log('err')
});
}
submitForm.before(validataFunc());
复制代码
这样修改之后,校验函数和提交表单数据的函数都变得纯净起来,迁移时也更加方便,不会互相影响。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END