乐趣区

关于前端:懒人封装懒惰模式

●本文旨在一些非凡的封装上
●个别会用于解决浏览器兼容性的封装
●然而看完会对你有一些启发也说不定哦 O(∩_∩)O~

一段简略的代码
●咱们在封装 ajax 申请的时候
●基于原生 js 的 ajax 代码, 如果思考到浏览器兼容问题
●那么咱们肯定会看到以下几段代码

// 规范浏览器下创立 ajax 对象
new XMLHttpRequest();
// 以下三种都是 IE 浏览器,对应不同版本
new ActiveXObject('Msxml12.XMLHTTP');
new ActiveXObject('Msxml13.XMLHTTP');
new ActiveXObject('Microsoft.XMLHTTP');

开始第一次封装
想到就做, 咱们就来进行一次封装试试看

function xhl_ajax(options) {
    // ...
    let xml = null
    if (window.XMLHttpRequest) {xml = new XMLHttpRequest()
    } else if (new ActiveXObject) {xml = new new ActiveXObject('Microsoft.XMLHTTP')
    } else {xhl = '你的浏览器可能不反对 ajax 申请, 请更换浏览器再试'}
    // ...
}

我这里并没有写残缺, 只是简略一个小示例
咱们来剖析一下这个事件
○咱们的判断品种可能有很多种, 比方 A B C D 四种

// 那么这一段代码就变成了
function xhl_ajax() {
    // ...
    if (A) {// ...} else if (B) {// ...} else if (C) {// ...} else if (D) {// ...} else {// ...}
    // ...
}

●代码可能就变成了这个样子
●可能有的小伙伴会想到, 我改成 策略模式 封装不就好了
我要说的不是这个问题
○不论你改成什么模式封装, 哪怕是腾飞模式
○如果你以后须要匹配到的内容是 D
○那么每调用一次, 都会从 A 开始判断一次
○而后达到 D

// 第一次调用
xhl_ajax() // 须要判断 A 不对, B 不对, C 不对, D 对了

// 第二次调用
xhl_ajax() // 须要判断 A 不对, B 不对, C 不对, D 对了

// ...

●设想一下, 如果调用了 100 次, 那么每次的前三个判断是不是都节约了呢
●如同是这样的
○那咱们是不是能够思考换一个形式来搞一下

懈怠模式封装这段代码
●咱们能不能考虑一下, 我封装结束的代码, 只有第一次调用的时候会判断
●前面调用的时候不在判断了, 那么是不是会节俭很多呢 ?
●想到就做
○准则就是多个事件顺次实现
○前一个胜利了, 前面的不做了
○只有胜利过一次, 当前就不在尝试了

1. 把咱们须要做的几个事件放在几个函数内

function createXHR1 () {return new XMLHttpRequest;}
function createXHR2 () {return new XActiveXObject("Microsoft.XMLHTTP");
}
function createXHR3 () {return new ActiveXObject("Msxml2.XMLHTTP");
}
function createXHR4 () {return new ActiveXObject("Msxml3.XMLHTTP");
}

●这样一来, 如果第一个能胜利, 那么咱们调用第一个函数就回失去对应的 ajax 对象了
●如果第一个不行, 咱们就尝试第二个

2. 接下来咱们把四个函数放在一个数组内, 遍历顺次执行
●只有找到一个适合的就行了

var xmls = [createXHR1, createXHR2, createXHR3, createXHR4]
let xml = null
for (var i = 0; i < xmls.length; i++) {
    // 一旦 xml 有内容了, 不再是 null 了, 那么间接完结循环
    if (xml) break
    // 否则就开始尝试
    xml = xmls[i]()}

●问题随之而来了, 如果第一个不对, 那么会报错
●我的代码就全副挂掉了

3. 尝试应用 try catch 解决问题
●为了不让我的代码挂掉
●咱们改用 try catch 来解决问题

var xmls = [createXHR1, createXHR2, createXHR3, createXHR4]
let xml = null
for (let i = 0; i < xmls.length; i++) {
    try {xml = xmls[i]()} catch(e) {}}

●错了也不须要做什么 , 间接下一次就好了
●看上去挺好, 然而问题仍旧没有解决

4. 独自制作一个函数
●我的准则就是, 让这个函数第一次调用和第二次调用不是一个函数就好了
●也就是我要在第一次调用结束当前批改这个函数

function createXHR() {
  // 定义一个 xhr 接管 ajax 对象
  // 定义一个 flag 开关,看看是否找到适合的创立 ajax 对象的办法
  // 定义一个数组,存储四种创立 ajax 对象的形式
  let xml = null,
    flag = false,
    xmls = [function () {return new XMLHttpRequest;},
      function () {return new ActiveXObject("Microsoft.XMLHTTP");
      },
      function () {return new ActiveXObject("Msxml2.XMLHTTP");
      },
      function () {return new ActiveXObject("Msxml3.XMLHTTP");
      }
    ];
  // 仍旧是循环遍历数组
  for (let i = 0, len = xmls.length; i < len; i++) {let curFn = ary[i];
    // 顺次执行,找到适合的创立 ajax 对象的办法
    try {xml = curFn();
      // 这里是外围,一旦找到适合的办法,那么咱们就把这个函数从新赋值给 createXHR
      createXHR = curFn;
      // 让开关为 true
      flag = true;
      break;
    } catch (e) {}}
  // 如果到最初开关仍旧为 false,证实四种办法都不适合,那么咱们就须要揭示浏览器降级
  if (!flag) {throw new Error("your browser is not support ajax, please change your browser,try again!");
  }
  // 最初返回 ajax 对象
  return xml;
}

●看似没有什么扭转,然而之一第 28 行的代码,有一个重写 createXHR
●这个是整个”惰性思维”的外围,也就是说,我只有在以后浏览器中,第一次执行 createXHR 的时候是这个函数
●一旦找到一个适合的创立 ajax 对象的办法当前,那么从第二次执行 createXHR 开始,就全部都是咱们之前数组中的某一个函数了
●再也不必循环判断,而是间接用一种无效的办法创立一个 ajax 对象了
●这个是一种 js 中的高级编程思维,如果了解不了,就用咱们最开始写的判断的模式来进行就能够,缓缓领会一段时间就能明确了

残缺代码

function createXHR() {
  let xml = null,
    flag = false,
    xmls = [function () {return new XMLHttpRequest;},
      function () {return new ActiveXObject("Microsoft.XMLHTTP");
      },
      function () {return new ActiveXObject("Msxml2.XMLHTTP");
      },
      function () {return new ActiveXObject("Msxml3.XMLHTTP");
      }
    ];
  for (let i = 0, len = xmls.length; i < len; i++) {let curFn = ary[i];
    try {xml = curFn();
      createXHR = curFn;
      flag = true;
      break;
    } catch (e) {}}
  if (!flag) {throw new Error("your browser is not support ajax, please change your browser,try again!");
  }
  return xml;
}

function xhl_ajax(options) {
    // ...
    const xml = createXHR()
    // ...
}

●从此以后, 你就去轻易调用吧
●只有第一次的时候会进行判断, 前面的时候都不会进行判断了
●间接就能应用那个最精确的了

退出移动版