允許在不改變原始對象的情況下,通過代理對象來訪問原始對象。代理對象可以在訪問原始對象之前或之后,添加一些額外的邏輯或功能。
科學上網過程
一般情況下,在訪問國外的網站,會顯示無法訪問
因為在dns解析過程,這些ip被禁止解析,所以顯示無法訪問
引入代理服務器,這個第三方的 ip 地址,不在被禁用的那批 ip 地址之列,我們可以順利訪問到這臺服務器。而這臺服務器的 DNS 解析過程,是正常的,所以它是可以順利訪問 Google.com 的。代理服務器在請求到 Google.com 后,將響應體轉發給你,使你得以間接地訪問到目標網址 —— 像這種第三方代替我們訪問目標對象的模式,就是代理模式。
應用
事件代理
利用事件冒泡的特性
<div id="father"><a href="#">鏈接1號</a><a href="#">鏈接2號</a><a href="#">鏈接3號</a><a href="#">鏈接4號</a><a href="#">鏈接5號</a><a href="#">鏈接6號</a></div><script>const father = document.getElementById('father')father.addEventListener('click', (e) => {if (e.target.tagName === 'A') {alert(`我是${e.target.innerHTML}`)}})</script></body>
虛擬代理
圖片懶加載
:
它是針對圖片加載時機的優化:在一些圖片量比較大的網站,比如電商網站首頁,或者團購網站、小游戲首頁等。如果我們嘗試在用戶打開頁面的時候,就把所有的圖片資源加載完畢,那么很可能會造成白屏、卡頓
等現象。
會采取==“先占位、后加載”==的方式來展示圖片 —— 在元素露出之前,我們給它一個 div 作占位,當它滾動到可視區域內時,再即時地去加載真實的圖片資源,這樣做既減輕了性能壓力、又保住了用戶體驗。
圖片預加載
。預加載主要是為了避免網絡不好、或者圖片太大時,頁面長時間給用戶留白的尷尬。常見的操作是先讓這個 img 標簽展示一個占位圖,然后創建一個 Image 實例,讓這個 Image 實例
的 src 指向真實的目標圖片地址、
觀察該 Image 實例的加載情況 —— 當其對應的真實圖片加載完畢后,即已經有了該圖片的緩存內容,再將 DOM 上的 img 元素的 src 指向真實的目標圖片地址。此時我們直接去取了目標圖片的緩存,所以展示速度會非常快,從占位圖到目標圖片的時間差會非常小、小到用戶注意不到,這樣體驗就會非常好了。
class PreLoadImage {// 獲取該實例對應的DOM節點constructor(imgNode) {this.imgNode = imgNode}setSrc(url) {this.imgNode.src=url}}class ProxyImg{//默認地址static url ="./../../static/1.png"//獲取目標元素constructor(targetImg){this.targetImg = targetImg}//操作虛擬imgsetSrc(url){// 設置默認圖片this.targetImg.setSrc(ProxyImg.url)//創建一個img實例const vitualImg = new Image()vitualImg.src = url//監聽img加載情況vitualImg.onload = ()=>{this.targetImg.setSrc(url)}}}const imgNode = document.getElementById('img')const proxyImg = new ProxyImg(new PreLoadImage(imgNode))proxyImg.setSrc('https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png')
在這個實例中,virtualImage
這個對象是一個“幕后英雄”,它始終存在于 JavaScript 世界中、代替真實 DOM 發起了圖片加載請求、完成了圖片加載工作,卻從未在渲染層面拋頭露面。因此這種模式被稱為“虛擬代理”模式。
緩存代理
它應用于一些計算量較大的場景里。
-
我們需要“用空間換時間”——當我們需要用到某個已經計算過的值的時候,不想再耗時進行二次計算,而是希望能從內存里去取出現成的計算結果。
-
這種場景下,就需要一個代理來幫我們在進行計算的同時,進行計算結果的緩存了。
//需求:對傳入的所有參數進行求和function addAll(){console.log('進行了一次計算');let sum = 0;for(let i = 0; i < arguments.length; i++){sum += arguments[i];}return sum;}function proxyAddAll(){//創造一個緩存池let cache = {};return function(...args){//將傳入的參數轉化為字符串,作為緩存的keylet key = args.join(',');if(key in cache){return cache[key];}return cache[key] = addAll(...args);}}let proxy = proxyAddAll();console.log(proxy(1,2,3,4,5)); //15console.log(proxy(1,2,3,4,5)); //15
保護代理
ES6中的Proxy
開婚介所的時候,為了保護用戶的私人信息,我們會在同事哥訪問小美的年齡的時候,去校驗同事哥是否已經通過了我們的實名認證;為了確保同事哥確實是一位有誠意的男士,當他想獲取小美的聯系方式時,我們會校驗他是否具有VIP 資格。所謂“保護代理”,就是在訪問層面做文章,在 getter 和 setter 函數里去進行校驗和攔截,確保一部分變量是安全的。