代理模式
续更...
一、缓存代理
- 这里进行描述:
/**
* 缓存代理可以为一些开销大的运算结果提供暂时的存储,
* 下次运算的时候,如果传进来的参数跟之前一致,则可以直接返回前面存储的运算结果。
*/
const mult = function () {
let a = 1;
for (let i = 0; i < arguments.length; i++) {
a = a * arguments[i];
}
console.log('a=', a);
return a;
}
定义好这个函数以后,我们分别调用两次:
mult(1,2,3); // a= 6
mult(1,2,3,4); // a= 24
- 现在再写一个缓存代理函数:
/**
* 现在我们加入缓存代理
* 这样的话,在调用缓存函数时,先执行缓存代理,再执行原函数
*/
const proxyMult = (function () {
const cache = {}; // 对象缓存
console.log('obj0', cache);
return function () {
const args = Array.prototype.join.call(arguments, ',');
if (args in cache) {
console.log('打印此处说明执行了缓存!!!');
console.log('obj1', cache);
return cache[args]
}
return cache[args] = mult.apply(this, arguments);
}
})()
这时候我们就不用直接调用原函数,而是调用代理函数即可。 调用:
proxyMult(2, 3, 4); // a= 24
proxyMult(2, 3, 4); // 执行缓存
proxyMult(2, 3, 4); // 执行缓存
来看看打印的结果:
obj0 {}
a= 24
打印此处说明执行了缓存!!!
obj1 { '2,3,4': 24 }
打印此处说明执行了缓存!!!
obj1 { '2,3,4': 24 }
结论:a 只打印了一次,obj 执行了2次调用。所以我们代理的目的达到了,当运算的开销变得非常大的时候,使用缓存代理可以减少不必要的重复性计算。
- 这里也可以使用 ES6 中的 Map:
const proxyMult = (function () {
const cache = new Map(); // Map 缓存
console.log('map0', cache);
return function () {
const args = Array.prototype.join.call(arguments, ',');
if (cache.has(args)) {
console.log('打印此处说明执行了缓存!!!');
console.log('map1', cache);
return cache.get(args)
}
return cache.set(args, mult.apply(this, arguments))
}
})()
proxyMult(2, 3, 4);
proxyMult(2, 3, 4);
proxyMult(2, 3, 4);
来看一下打印结果:
map0 Map(0) {}
a= 24
打印此处说明执行了缓存!!!
map1 Map(1) { '2,3,4' => 24 }
打印此处说明执行了缓存!!!
map1 Map(1) { '2,3,4' => 24 }
同样的,arguments 也可以用 ...rest 参数去进行改进...
推荐使用 ES6 新增的 Map 数据结构。
const proxyMult = () => {
const cache = new Map();
return (...rest) => {
if (cache.has(rest.toString())) {
return cache.get(rest.toString())
}
return cache.set(rest.toString(), mult(...rest));
// or
return cache.set(rest.toString(), mult.apply(this, rest));
}
}
参考来源 《JavaScript 设计模式与开发实践》
第一篇文字,还望各位大佬不吝指点一二 ~