你所不知道的惰性函数。

724 阅读2分钟
原文链接: mp.weixin.qq.com

从能力检测开始说起。


概念

能力检测,又可以称为特性检测。它的目标是识别浏览器的能力,它的基本模式如下:

// 使用 object.property

if (object.property) {

}

例子

在浏览器中可以采用 JavaScript 检测是否支持 WebP,对支持 WebP 的用户输出 WebP 图片,否则输出其他格式的图片。

// 简化写法

function isSupportWebp() {

var isSupportWebp = false; try { isSupportWebp = document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') == 0; } catch(err) { console.log(err); } return isSupportWebp;}

上面代码的问题在于我们每当使用一次 isSupportWebp 时都会进行一次判断。为了防止每次调用都判断的问题,我们可以用一个变量来缓存。

function isSupportWebp() {  var isSupportWebp = false;  try {    isSupportWebp = document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') == 0;  } catch(err) {    console.log(err);  }  return isSupportWebp;

}

var isSupportWebpTmp = isSupportWebp();

这样我们可以使用 isSupportWebpTmp 来判定浏览器是否支持 WebP 格式的图片,但缺点是多了一个变量作为缓存,代码有点冗余。

我们也可以使用立即执行的匿名函数的形式来进行判断。

var isSupportWebp = (function () {  var isSupportWebp = false;  try {    isSupportWebp = document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') == 0;  } catch(err) {    console.log(err);  }  return isSupportWebp;})();

以上代码缺点是多了一个立即执行的匿名函数,当我在声明的时候,这个函数已经执行过一遍了。那有没有一种方法是在运行时才执行呢?

答案是肯定的。这时候可以利用惰性函数,代码如下:

// 惰性函数function isSupportWebp() {  var isSupportWebpTmp = false;  try {    isSupportWebpTmp = document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') == 0;  } catch(err) {    console.log(err);  }  isSupportWebp = function () {    return isSupportWebpTmp;  }  return isSupportWebp();}

综上,当我们每次都需要进行条件判断,实际上只需要判断一次,接下来的使用方式都不会发生改变的时候,想想是否可以考虑使用惰性函数,能力检测就是其中一种类型。

更多应用

DOM 事件添加中,为了兼容现代浏览器和 IE 浏览器,我们需要对浏览器环境进行一次判断:

// 惰性函数function addEvent(type, el, fn) {  if (window.addEventListener) {

    addEvent = function (type, el, fn) {

      el.addEventListener(type, fn, false);

    }

  } else if (window.attachEvent) {

    addEvent = function (type, el, fn) {

      el.attachEvent('on' + type, fn);

    }

  }

}