给对象动态添加职责的模式是装饰者模式。装饰者能够在不改变对象自身的基础上,在程序运行前给对象动态地添加职责。跟继承相比,装饰者是轻便灵活的模式
当直接访问本体不方便或者不符合需要时,为这个本体提供一个替代者。为对象动态加入行为。
代理模式强调一种关系,这种关系可以静态的表达,也就是说,这种关系一开始就可以被确定。而装饰者用于一开始不能确定对象的全部功能时。
代理模式通常只有一层代理-本体的作用,而装饰者模式经常会形成一条长长的装饰链。
Function.prototype.after = function (afterFn) {
const _self = this;
return function () {
const ret = _self.apply(this, arguments);
afterFn.apply(this, arguments);
return ret;
};
};
const log1 = function () {
console.log("上报标签为:", this.getAttribute("tag"));
};
let showLogin1 = function () {
console.log("登录");
};
showLogin1 = showLogin1.after(log1);
document.getElementById("button").onclick = showLogin1;
AOP 可修改函数的参数
Function.prototype.before = function (beforeFn) {
// 保存原函数的引用
const _self = this;
// 返回包含原函数和新函数的代理函数
return function () {
beforeFn.apply(this, arguments); // 执行 before 新函数
return _self.apply(this, arguments); // 执行 func 函数并返回原函数的执行结果
};
};
可以看到 beforeFn 和原函数_self 公用一组参数列表 arguemnts,当我们在 beforeFn 的函数体内改变 arguments 的时候,_self 接受的参数也会改变。
使用场景:给 ajax 新增参数;
Function.prototype.before = function (beforeFn) {
// 保存原函数的引用
const _self = this;
// 返回包含原函数和新函数的代理函数
return function () {
beforeFn.apply(this, arguments); // 执行 before 新函数
return _self.apply(this, arguments); // 执行 func 函数并返回原函数的执行结果
};
};
let ajax = (type, url, params) => {
console.log(params);
};
ajax = ajax.before(function (type, url, param) {
param.header = "application/json";
});
ajax("type", "xx", { token: "token" });
使用 AOP 的弊端
let fnc = function () {
console.log(1);
};
fnc.a = "1";
fnc = fnc.before(() => {
console.log(1);
});
console.log(fnc.a); // undefined