代理模式(Proxy Pattern)
为其他对象提供一种代理以控制对这个对象的访问。
常用的代理模式变种有以下几种:
- 保护代理
- 虚拟代理
- 缓存代理
1. 保护代理
保护代理用于控制不同权限的对象对目标对象的访问
- 举例
class Car {
drive() {
return "driving";
};
}
class CarProxy {
constructor(driver) {
this.driver = driver;
}
drive() {
// 保护代理,仅18岁才能开车
return (this.driver.age < 18) ? "too young to drive" : new Car().drive();
};
}
2. 虚拟代理
虚拟代理可应用于:
图片懒加载
、惰性加载
、合并http请求
等
- 举例:图片懒加载
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>图片懒加载</title>
<style>
img {
display: block;
width: 400px;
height: 300px;
margin-bottom: 200px;
}
</style>
</head>
<body>
<img data-src="./images/1.jpg" alt="">
<img data-src="./images/2.jpg" alt="">
<img data-src="./images/3.jpg" alt="">
<img data-src="./images/4.jpg" alt="">
</body>
<script>
var imgs = document.querySelectorAll('img');
//offsetTop是元素与offsetParent的距离,循环获取直到页面顶部
function getTop(e) {
var T = e.offsetTop;
while(e = e.offsetParent) {
T += e.offsetTop;
}
return T;
}
function lazyLoad(imgs) {
var H = document.documentElement.clientHeight;//获取可视区域高度
var S = document.documentElement.scrollTop || document.body.scrollTop;
for (var i = 0; i < imgs.length; i++) {
if (H + S > getTop(imgs[i])) {
imgs[i].src = imgs[i].getAttribute('data-src');
}
}
}
window.onload = window.onscroll = function () { //onscroll()在滚动条滚动的时候触发
lazyLoad(imgs);
}
</script>
</html>
3. 缓存代理
缓存代理可应用于:
缓存ajax异步请求数据
、计算乘积
等
- 举例:缓存ajax请求数据
const getData = (function() {
const cache = {};
return function(url) {
if (cache[url]) {
return Promise.resolve(cache[url]);
}
return $.ajax.get(url).then((res) => {
cache[url] = res;
return res;
}).catch(err => console.error(err))
}
})();
getData('/getData'); // 发起http请求
getData('/getData'); // 返回缓存数据
总结
代理模式包括许多小分类,在 JavaScript 开发中最常用的是虚拟代理和缓存代理。虽然代理模式非常有用,但我们在编写业务代码的时候,往往不需要去预先猜测是否需要使用代理模式。当真正发现不方便直接访问某个对象的时候,再编写代理也不迟。