《JavaScript设计模式与开发实践》——学习笔记(惰性加载函数)

185 阅读2分钟

适用场景

需要根据场景判断出运行函数,且场景值不改变。

实现示例(惰性加载函数)

lazyLoad = function (...args) {
  if (condition1) {
      lazyLoad = () => {
          // 做了一下事情...
      }
  } else if (condition2) {
      lazyLoad = () => {
          // 做了一下事情...
      }
  } else {
      lazyLoad = () => {
          // 做了一下事情...
      }
  }
  lazyLoad.apply(this, args);
}

原始版本

function imgPreview(el) {
     if (el.target.tagName.toLowerCase() !== 'img') {
         return;
     }
     // ios端纷享侧使用prewiew插件有问题,走内部的软件
     if (FS.CONST.isFSBrowser) {
         // 用移动端组件...
     } else {
         // 用web端组件...
     }
 }
 iframe.contentWindow.addEventListener('click', imgPreview);

该方法通过if来判断代码的运行环境,来区分调用不同的预览组件。

但这有个弊端就是,每次触发click事件,都要进行一次if判断,而代码的运行环境是不会在函数每次调用间改变的(至页面加载之后,移动端就会一直运行于移动端,web端就一直运行于web端)。

利用惰性加载函数优化

let imgPreview = (e) => {
  // ios端纷享侧使用prewiew插件有问题,走内部的软件
  if (FS.CONST.isFSBrowser) {
      imgPreview = (el) => {
          if (el.target.tagName.toLowerCase() !== 'img') {
              return;
          }
          // 用移动端组件...
      };
  } else {
      imgPreview = (el) => {
          if (el.target.tagName.toLowerCase() !== 'img') {
              return;
          }
          // 用web端组件...
      };
  }
  imgPreview(e);
};

利用惰性加载函数,可以在imgPreview的第一次调用时,进行环境判断,并将对应的处理函数重新赋值给imgPreview,使得之后的调用可以直接进行处理而不用再判断环境。

但这仍有一个问题,就是执行函数(重新赋值过后的imgPreview)里面的拦截逻辑需要写两次(判断dom是否是img),且这两处的拦截逻辑是应该一直相同的。

封装变化(代理模式)

let imgPreview = (e) => {
    // ios端纷享侧使用prewiew插件有问题,走内部的软件
    if (FS.CONST.isFSBrowser) {
        imgPreview = (el) => {
            // 用移动端组件...
        };
    } else {
        imgPreview = (el) => {
            // 用web端组件...
        };
    }
    imgPreview(e);
};
const imgClickHandler = (el) => {
    if (el.target.tagName.toLowerCase() !== 'img') {
        return;
    }
    imgPreview(el);
};
iframe.contentWindow.addEventListener('click', imgClickHandler);

这个是代码的最终版本,《JavaScript设计模式与开发实践》中有一句话是“当我们想办法把程序中变化的部分封装好之后,剩下的即是稳定而可复用的部分了”。 我们可以将代码中“不变的”,即imgPreview的拦截逻辑,抽离处理。将“变化的”,即不同环境下不同组件的调用,封装起来。