聊聊代理模式

前言

代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。 下面就介绍最经常使用的几种场景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

相关文章
相关标签/搜索