个人随笔
目录
当前位置: 首页 JS JS惰性载入函数
JS惰性载入函数
2020-05-21 23:45:01
摘要:JS、JS惰性载入函数

因为浏览器之间行为的差异,多数 JavaScript 代码包含了大量的 if 语句,将执行引导到正确的代码中。看看下面来自上一章的 createXHR()函数。

  1. function createXHR(){
  2. if (typeof XMLHttpRequest != "undefined"){
  3. return new XMLHttpRequest();
  4. } else if (typeof ActiveXObject != "undefined"){
  5. if (typeof arguments.callee.activeXString != "string"){
  6. var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
  7. "MSXML2.XMLHttp"],
  8. i,len;
  9. for (i=0,len=versions.length; i < len; i++){
  10. try {
  11. new ActiveXObject(versions[i]);
  12. arguments.callee.activeXString = versions[i];
  13. break;
  14. } catch (ex){
  15. //跳过
  16. }
  17. }
  18. }
  19. return new ActiveXObject(arguments.callee.activeXString);
  20. } else {
  21. throw new Error("No XHR object available.");
  22. }
  23. }

每次调用 createXHR()的时候,它都要对浏览器所支持的能力仔细检查。首先检查内置的 XHR,然后测试有没有基于 ActiveX 的 XHR,最后如果都没有发现的话就抛出一个错误。每次调用该函数都是这样,即使每次调用时分支的结果都不变:如果浏览器支持内置 XHR,那么它就一直支持了,那么这种测试就变得没必要了。即使只有一个 if 语句的代码,也肯定要比没有 if 语句的慢,所以如果 if 语句不必每次执行,那么代码可以运行地更快一些。解决方案就是称之为惰性载入的技巧。惰性载入表示函数执行的分支仅会发生一次。有两种实现惰性载入的方式,第一种就是在函数被调用时再处理函数。在第一次调用的过程中,该函数会被覆盖为另外一个按合适方式执行的函数,这样任何对原函数的调用都不用再经过执行的分支了。例如,可以用下面的方式使用惰性载入重写createXHR()。

  1. function createXHR(){
  2. if (typeof XMLHttpRequest != "undefined"){
  3. createXHR = function(){
  4. return new XMLHttpRequest();
  5. };
  6. } else if (typeof ActiveXObject != "undefined"){
  7. createXHR = function(){
  8. if (typeof arguments.callee.activeXString != "string"){
  9. var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
  10. "MSXML2.XMLHttp"],
  11. i, len;
  12. for (i=0,len=versions.length; i < len; i++){
  13. try {
  14. new ActiveXObject(versions[i]);
  15. arguments.callee.activeXString = versions[i];
  16. break;
  17. } catch (ex){
  18. //skip
  19. }
  20. }
  21. }
  22. return new ActiveXObject(arguments.callee.activeXString);
  23. };
  24. } else {
  25. createXHR = function(){
  26. throw new Error("No XHR object available.");
  27. };
  28. }
  29. return createXHR();
  30. }

在这个惰性载入的 createXHR()中,if 语句的每一个分支都会为 createXHR 变量赋值,有效覆盖了原有的函数。最后一步便是调用新赋的函数。下一次调用 createXHR()的时候,就会直接调用被分配的函数,这样就不用再次执行 if 语句了。第二种实现惰性载入的方式是在声明函数时就指定适当的函数。这样,第一次调用函数时就不会损失性能了,而在代码首次加载时会损失一点性能。以下就是按照这一思路重写前面例子的结果。

  1. var createXHR = (function(){
  2. if (typeof XMLHttpRequest != "undefined"){
  3. return function(){
  4. return new XMLHttpRequest();
  5. };
  6. } else if (typeof ActiveXObject != "undefined"){
  7. return function(){
  8. if (typeof arguments.callee.activeXString != "string"){
  9. var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
  10. "MSXML2.XMLHttp"],
  11. i, len;
  12. for (i=0,len=versions.length; i < len; i++){
  13. try {
  14. new ActiveXObject(versions[i]);
  15. arguments.callee.activeXString = versions[i];
  16. break;
  17. } catch (ex){
  18. //skip
  19. }
  20. }
  21. }
  22. return new ActiveXObject(arguments.callee.activeXString);
  23. };
  24. } else {
  25. return function(){
  26. throw new Error("No XHR object available.");
  27. };
  28. }
  29. })();

这个例子中使用的技巧是创建一个匿名、自执行的函数,用以确定应该使用哪一个函数实现。实际的逻辑都一样。不一样的地方就是第一行代码(使用 var 定义函数)、新增了自执行的匿名函数,另外每个分支都返回正确的函数定义,以便立即将其赋值给 createXHR()。惰性载入函数的优点是只在执行分支代码时牺牲一点儿性能。至于哪种方式更合适,就要看你的具体需求而定了。不过这两种方式都能避免执行不必要的代码。

 163

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2