自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官:說(shuō)說(shuō)你對(duì)代理模式的理解?應(yīng)用場(chǎng)景?

開(kāi)發(fā) 前端
代理模式的關(guān)鍵是,當(dāng)客戶不方便直接訪問(wèn)一個(gè)對(duì)象或者不滿足需要時(shí),提供一個(gè)替身對(duì)象來(lái)控制這個(gè)對(duì)象的訪問(wèn),客戶實(shí)際上訪問(wèn)的是替身對(duì)象。

[[433461]]

一、是什么

代理模式(Proxy Pattern)是為一個(gè)對(duì)象提供一個(gè)代用品或占位符,以便控制對(duì)它的訪問(wèn)

代理模式的關(guān)鍵是,當(dāng)客戶不方便直接訪問(wèn)一個(gè)對(duì)象或者不滿足需要時(shí),提供一個(gè)替身對(duì)象來(lái)控制這個(gè)對(duì)象的訪問(wèn),客戶實(shí)際上訪問(wèn)的是替身對(duì)象

在生活中,代理模式的場(chǎng)景是十分常見(jiàn)的,例如我們現(xiàn)在如果有租房、買房的需求,更多的是去找鏈家等房屋中介機(jī)構(gòu),而不是直接尋找想賣房或出租房的人談。此時(shí),鏈家起到的作用就是代理的作用

二、使用

在ES6中,存在proxy構(gòu)建函數(shù)能夠讓我們輕松使用代理模式:

  1. const proxy = new Proxy(target, handler); 

關(guān)于Proxy的使用可以翻看以前的文章

而按照功能來(lái)劃分,javascript代理模式常用的有:

  • 緩存代理
  • 虛擬代理

緩存代理

緩存代理可以為一些開(kāi)銷大的運(yùn)算結(jié)果提供暫時(shí)的存儲(chǔ),在下次運(yùn)算時(shí),如果傳遞進(jìn)來(lái)的參數(shù)跟之前一致,則可以直接返回前面存儲(chǔ)的運(yùn)算結(jié)果

如實(shí)現(xiàn)一個(gè)求積乘的函數(shù),如下:

  1. var muti = function () { 
  2.   console.log("開(kāi)始計(jì)算乘積"); 
  3.   var a = 1; 
  4.   for (var i = 0, l = arguments.length; i < l; i++) { 
  5.     a = a * arguments[i]; 
  6.   } 
  7.   return a; 
  8. }; 

現(xiàn)在加入緩存代理,如下:

  1. var proxyMult = (function () { 
  2.   var cache = {}; 
  3.   return function () { 
  4.     var args = Array.prototype.join.call(arguments, ","); 
  5.     if (args in cache) { 
  6.       return cache[args]; 
  7.     } 
  8.     return (cache[args] = mult.apply(this, arguments)); 
  9.   }; 
  10. })(); 
  11.  
  12. proxyMult(1, 2, 3, 4); // 輸出:24 
  13. proxyMult(1, 2, 3, 4); // 輸出:24 

當(dāng)?shù)诙握{(diào)用 proxyMult(1, 2, 3, 4) 時(shí),本體 mult 函數(shù)并沒(méi)有被計(jì)算,proxyMult 直接返回了之前緩存好的計(jì)算結(jié)果

虛擬代理

虛擬代理把一些開(kāi)銷很大的對(duì)象,延遲到真正需要它的時(shí)候才去創(chuàng)建

常見(jiàn)的就是圖片預(yù)加載功能:

未使用代理模式如下:

  1. let MyImage = (function(){ 
  2.     let imgNode = document.createElement( 'img' ); 
  3.     document.body.appendChild( imgNode ); 
  4.     // 創(chuàng)建一個(gè)Image對(duì)象,用于加載需要設(shè)置的圖片 
  5.     let img = new Image; 
  6.  
  7.     img.onload = function(){ 
  8.         // 監(jiān)聽(tīng)到圖片加載完成后,設(shè)置src為加載完成后的圖片 
  9.         imgNode.src = img.src; 
  10.     }; 
  11.  
  12.     return { 
  13.         setSrc: function( src ){ 
  14.             // 設(shè)置圖片的時(shí)候,設(shè)置為默認(rèn)的loading圖 
  15.             imgNode.src = 'https://img.zcool.cn/community/01deed576019060000018c1bd2352d.gif'
  16.             // 把真正需要設(shè)置的圖片傳給Image對(duì)象的src屬性 
  17.             img.src = src; 
  18.         } 
  19.     } 
  20. })(); 
  21.  
  22. MyImage.setSrc( 'https://xxx.jpg' ); 

MyImage對(duì)象除了負(fù)責(zé)給img節(jié)點(diǎn)設(shè)置src外,還要負(fù)責(zé)預(yù)加載圖片,違反了面向?qū)ο笤O(shè)計(jì)的原則——單一職責(zé)原則

上述過(guò)程loding則是耦合進(jìn)MyImage對(duì)象里的,如果以后某個(gè)時(shí)候,我們不需要預(yù)加載顯示loading這個(gè)功能了,就只能在MyImage對(duì)象里面改動(dòng)代碼

使用代理模式,代碼則如下:

  1. // 圖片本地對(duì)象,負(fù)責(zé)往頁(yè)面中創(chuàng)建一個(gè)img標(biāo)簽,并且提供一個(gè)對(duì)外的setSrc接口 
  2. let myImage = (function(){ 
  3.     let imgNode = document.createElement( 'img' ); 
  4.     document.body.appendChild( imgNode ); 
  5.  
  6.     return { 
  7.         //setSrc接口,外界調(diào)用這個(gè)接口,便可以給該img標(biāo)簽設(shè)置src屬性 
  8.         setSrc: function( src ){ 
  9.             imgNode.src = src; 
  10.         } 
  11.     } 
  12. })(); 
  13. // 代理對(duì)象,負(fù)責(zé)圖片預(yù)加載功能 
  14. let proxyImage = (function(){ 
  15.     // 創(chuàng)建一個(gè)Image對(duì)象,用于加載需要設(shè)置的圖片 
  16.     let img = new Image; 
  17.     img.onload = function(){ 
  18.         // 監(jiān)聽(tīng)到圖片加載完成后,給被代理的圖片本地對(duì)象設(shè)置src為加載完成后的圖片 
  19.         myImage.setSrc( this.src ); 
  20.     } 
  21.     return { 
  22.         setSrc: function( src ){ 
  23.             // 設(shè)置圖片時(shí),在圖片未被真正加載好時(shí),以這張圖作為loading,提示用戶圖片正在加載 
  24.             myImage.setSrc( 'https://img.zcool.cn/community/01deed576019060000018c1bd2352d.gif' ); 
  25.             img.src = src; 
  26.         } 
  27.     } 
  28. })(); 
  29.  
  30. proxyImage.setSrc( 'https://xxx.jpg' ); 

使用代理模式后,圖片本地對(duì)象負(fù)責(zé)往頁(yè)面中創(chuàng)建一個(gè)img標(biāo)簽,并且提供一個(gè)對(duì)外的setSrc接口;

代理對(duì)象負(fù)責(zé)在圖片未加載完成之前,引入預(yù)加載的loading圖,負(fù)責(zé)了圖片預(yù)加載的功能

上述并沒(méi)有改變或者增加MyImage的接口,但是通過(guò)代理對(duì)象,實(shí)際上給系統(tǒng)添加了新的行為

并且上述代理模式可以發(fā)現(xiàn),代理和本體接口的一致性,如果有一天不需要預(yù)加載,那么就不需要代理對(duì)象,可以選擇直接請(qǐng)求本體。其中關(guān)鍵是代理對(duì)象和本體都對(duì)外提供了 setSrc 方法

三、應(yīng)用場(chǎng)景

現(xiàn)在的很多前端框架或者狀態(tài)管理框架都使用代理模式,用于監(jiān)聽(tīng)變量的變化

使用代理模式代理對(duì)象的訪問(wèn)的方式,一般又被稱為攔截器,比如我們?cè)陧?xiàng)目中經(jīng)常使用 Axios 的實(shí)例來(lái)進(jìn)行 HTTP 的請(qǐng)求,使用攔截器 interceptor 可以提前對(duì) 請(qǐng)求前的數(shù)據(jù) 服務(wù)器返回的數(shù)據(jù)進(jìn)行一些預(yù)處理

以及上述應(yīng)用到的緩存代理和虛擬代理

參考文獻(xiàn)

https://juejin.cn/post/6844903555036364814#heading-2

https://juejin.cn/post/6992510837403418654#heading-7

 

https://sothx.com/2021/06/26/proxy/

 

責(zé)任編輯:武曉燕 來(lái)源: JS每日一題
相關(guān)推薦

2021-11-09 08:51:13

模式命令面試

2021-11-03 14:10:28

工廠模式場(chǎng)景

2021-11-10 07:47:49

組合模式場(chǎng)景

2021-11-11 16:37:05

模板模式方法

2021-11-22 23:50:59

責(zé)任鏈模式場(chǎng)景

2021-09-16 07:52:18

算法應(yīng)用場(chǎng)景

2021-08-16 08:33:26

git

2021-11-04 06:58:32

策略模式面試

2021-09-06 10:51:27

TypeScriptJavaScript

2021-09-28 07:12:09

測(cè)試路徑

2021-09-29 07:24:20

場(chǎng)景數(shù)據(jù)

2021-09-10 06:50:03

TypeScript裝飾器應(yīng)用

2021-10-08 09:59:32

冒泡排序場(chǎng)景

2021-10-13 18:01:33

快速排序場(chǎng)景

2021-09-08 07:49:34

TypeScript 泛型場(chǎng)景

2021-10-09 10:25:41

排序應(yīng)用場(chǎng)景

2021-05-31 10:35:34

TCPWebSocket協(xié)議

2021-06-01 08:25:06

Node.jsJavaScript運(yùn)行

2021-10-18 07:51:39

回溯算法面試

2021-10-11 09:38:41

開(kāi)源
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)