聊聊代理模式

前言

代理模式是爲一個對象提供一個代用品或佔位符,以便控制對它的訪問。 下面就介紹最經常使用的幾種場景html

保護代理

例如做爲孩子咱們總但願他健康成長,在成長路上遇到的煩惱會被家長解決,這樣來看其實就是保護代理,下面用一段僞代碼來實現。vue

function Children() {
  this.knowledge = [];
}
Children.prototype.Study = function(content) {
  // ...學習,增長知識
  this.knowledge.push(content);
};
var Parent = (function() {
  var small = new Children();
  return {
    knowledge: function(content) {
      if (content === "bad") {
        // 壞的,過濾掉
      } else {
        small.Study(content);
      }
    }
  };
})();
複製代碼

上面用僞代碼的形式來實現了一個保護例子,不過你可能會困惑,這樣不是畫蛇添足麼,咱們徹底能夠在Children內部實現,不過這樣作jquery

  1. 增長了程序耦合度,若是想要過濾更多,或者某一天不過濾了,還要更改代碼
  2. 違背了單一原則,對於代碼的閱讀和維護,形成了更多的成本

緩存代理

緩存代理是很實用的一個例子,例如一個階乘函數,計算 n 的階乘,最多須要保存 n 個調用記錄,咱們可能這樣寫緩存

function factorial(n) {
  if (n === 1) return 1;
  return n * factorial(n - 1);
}
factorial(5); // 120
複製代碼

不過若是重複計算 5 或者 10,很明顯形成了屢次浪費,這個時候就可使用代理,把結果緩存下來,若是存在就直接返回。dom

function next(n, total) {
  if (n === 1) return 1;
  return n * factorial(n - 1);
}
var factorial = (function() {
  var obj = {};
  return function(v) {
    if (obj[v]) {
      return obj[v];
    }
    obj[v] = next(v);
    return obj[v];
  };
})();
factorial(5); // 120
factorial(5); // 120
複製代碼

上面就將結果緩存了下來,除此以外還能夠引用在異步請求中能夠節省加載的時間。異步

應用場景

上面簡單介紹了兩種模式,實際上還有不少,好比虛擬代理、遠程代理、防火牆代理等,不過這裏不作介紹了,下面看看使用場景。函數

jquery

jquery基於鏈式調用,好比$('.a').html('').text(''),不過你會不會很好奇,$()調用的時候它是怎麼記錄這個值的呢,每次調用$()存儲的 dom 都不相同,實際上它就是借用了代理模式,這裏直接貼代碼了學習

function Jquery(dom) {
  this.dom = dom;
}
// 代理者
function $(dom) {
  return new Jquery(dom);
}
$.prototype = Jquery.prototype = {
  // 只作演示,不涉及具體代碼
  html() {
    return this;
  },
  text() {
    return this;
  }
};
$(".a")
  .html("")
  .text("");
複製代碼

vue

咱們在使用 vue 的時候給定了配置項data,它是一個對象,裏面的屬性會被 vue 響應式處理,咱們能夠經過this.的方式來簡單訪問,也是用了代理模式,下面就用一段僞 vue 代碼來講明ui

class Mvvm {
  constructor(option = {}) {
    this.$option = option;
    this._data = option.data || {};
    // 代理數據
    for (const name in this._data) {
      Object.defineProperty(this, name, {
        configurable: true,
        enumerable: true,
        get() {
          return this._data[name];
        },
        set(v) {
          return (this._data[name] = v);
        }
      });
    }
  }
}
export default Mvvm;
複製代碼

能夠複製上面代碼,本身簡單試下。this

相關文章
相關標籤/搜索