惰性载入函数

531 阅读1分钟

惰性载入表示函数执行的分支仅会发生一次。有两种实现惰性载入的方式:

一、在函数被调用时再处理函数

在第一次调用的过程中,该函数会被覆盖为另外一个按合适方式执行的函数,这样任何对原函数的调用都不用再经过执行的分支了。

function createXHR () {
  if (typeof XMLHttpRequest != 'undefined') {
    createXHR = function () {
      return new XMLHttpRequest()
    }
  } else if (typeof ActiveXObject != 'undefined') {
    createXHR = function () {
      if (typeof arguments.callee.activeXString != 'string') {
        let versions = ['MSXML2.XMLHttp.6.0', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp'], i, len
        for (i = 0, len = versions.length; i < len; i++) {
          try {
            new ActiveXObject(versions[i])
            arguments.callee.activeXString = versions[i]
            break
          } catch (ex) {
            // skip
          }
        }
      }
      return new ActiveXObject(arguments.callee.activeXString)
    }
  } else {
    createXHR = function () {
      throw new Error('No XHR object available.')
    }
  }
  return createXHR()
}

在这个惰性载入的createXHR()中,if语句的每一个分支都会为createXHR变量赋值,有效覆盖了原有的函数。最后一步便是调用新赋的函数。下一次调用createXHR()的时候,就会直接调用被分配的函数,这样就不用再次执行if语句了。

二、在声明函数时就指定适当的函数

这样,第一次调用函数时就不会损失性能了,而在代码首次加载时会损失一点性能。

const createXHR = (function () {
  if (typeof XMLHttpRequest != 'undefined') {
    return function () {
      return new XMLHttpRequest()
    }
  } else if (typeof ActiveXObject != 'undefined') {
    return function () {
      if (typeof arguments.callee.activeXString != 'string') {
        let [versions, i, len] = [['MSXML2.XMLHttp.6.0', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp'], 0, 0]
        for (i = 0, len = versions.length; i < len; i++) {
          try {
            new ActiveXObject(versions[i])
            arguments.callee.activeXString = versions[i]
            break
          } catch (ex) {
            // skip
          }
        }
      }
      return new ActiveXObject(arguments.callee.activeXString)
    }
  } else {
    return function () {
      throw new Error('No XHR object available.')
    }
  }
})()

// 使用方法
let xhr = createXHR()
xhr.onreadystatechange = function () {
  if (xhr.readyState == 4) {
    if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
      console.log(xhr.responseText)
    } else {
      console.log('Request was unsuccessful: ' + xhr.status)
    }
  }
}
xhr.onprogress = function (event) {
  if (event.lengthComputable) {
    console.log('Received ' + event.loaded + ' of ' + event.total + ' bytes.')
  }
}
xhr.open('GET', 'example.txt')
xhr.send(null)