Zepto 源码剖析 2 - Polyfill 设想

在进入 Zepto Core 模块代码之前,本节简朴枚举 Zepto 及其他开源库中一些 Polyfill 的设想思绪与完成技能。

触及模块:IE/IOS 3/Detect.

IE 模块 / CSSOM 相干 Polyfill

Zepto 的 IE 模块 src/ie.js 中仅仅包含了一个兼容性降级逻辑,虽简朴其完成也值得进修:

(function() {
  try {
    getComputedStyle(undefined);
  } catch (e) {
    var nativeGetComputedStyle = getComputedStyle;
    window.getComputedStyle = function(element, pseudoElement) {
      try {
        return nativeGetComputedStyle(element, pseudoElement);
      } catch (e) {
        return null;
      }
    };
  }
})();

低版本兼容情势(以 IE 7 为例)挪用 getComputedStyle 会涌现找不到该要领的题目),已在高版本 IE 取得支撑

The value of the property 'getComputedStyle' is null or undefined, not a Function object

望文生义该要领用于取得元素的动态盘算属性,此处在 windows 对象上显式挂载包含 Failover 的 getComputedStyle 要领,使得该要领不存在时的挪用代码仍可继承运转,不可成壅塞。更细致的多浏览器兼容计划能够经由过程浏览 jQuery css API 源码找到。

此模块包含的设想思绪即为Failover 预 catch以婚配降级计划

从该题目中能够引伸出一个罕见题目,CSSOM 的浏览器支撑水平远远低于 DOM 的支撑水平,W3C 关于 Document Object Model (DOM) Level 2 Style Specification 的声明早已于 2000 岁终时候完成,但是 CSSOM 的官方范例 CSS Object Model (CSSOM) 由于 CSS 3 多管道演进的完成体式格局影响,仍未推出厂商公认的现实范例,因而关于 CSSOM 的操纵设想与跨浏览器兼容性测试,jQuery 仍有极好的参考价值。同时,开源社区中也存在大批的 Polyfill(腻子剧本)用于对低版本浏览器经由过程 JavaScript 附加逻辑的体式格局附加较新潮的特征,能够在 Modernizr/Modernizr 相似的代码源中找到。浏览 Polyfill 每每能够取得对 原型链和 JS 面向对象设想头脑的更深入熟悉,以及更深条理的设想技能,以以下的一个 IE 8 opacity 属性的 Polyfill 函数为例,完成该函数的技能已远远逾越了本身完成的功用:

//\ 正则表达式,婚配满足 alpha 定义划定规矩的字符串
var opacityre = /\b\s*alpha\s*\(\s*opacity\s*=\s*(\d+)\s*\)/;

//\ 原型链挂载,直接将 opacity 放入 CSSStyleDeclaration 中
defineProperty(window.CSSStyleDeclaration.prototype, "opacity", {

  //\ getter 函数,自定义 toString 要领
  get: function() {
    var m = this.filter.match(opacityre);
    return m ? (m[1] / 100).toString() : "";
  },
  
  //\ setter 函数,将 opacity 值写入 alpha(opacity=$value) 的情势,供浏览器运用
  set: function(value) {
    this.zoom = 1;
    var found = false;
    if (value < 1) {
      value = " alpha(opacity=" + Math.round(value * 100) + ")";
    } else {
      value = "";
    }
    this.filter = this.filter.replace(opacityre, function() {
      found = true;
      return value;
    });
    if (!found && value) {
      this.filter += value;
    }
  }
});

此剧本包含的设想思绪为应用 Getter/Setter 掌握差别高低文中属性的设置与猎取,一样的思绪即为 Vue.js 数据绑定的设想源泉。

IOS 3 模块 / 言语特征 Polyfill

Zepto 默许编译中未包含的 IOS 3 模块 src/ios3.js 包含了两个函数的兼容完成,现实上属于言语特征 Polyfill,这类 Polyfill 重要用于处理言语生长与完成差别步等题目,并供应一些完成优越的大众要领用于营业开辟,最罕见的两类例子:

  • Lodash / Underscore 供应大批完成优越的东西函数
  • TypeScript 供应范例体系,现实这门言语也可被当作 Polyfill 看,由于 ECMAScript 提案中,已包含了一个静态范例体系 的发起

IOS 3 模块中的两个 Polyfill 分别为 String / Array 两个包装类原型上挂载了一个罕见要领:

    //\ Line 6
    String.prototype.trim = function() {
      //\ 将字符串首末的空格剪除
      return this.replace(/^\s+|\s+$/g, "");
    };

该要领原始定义于 ES 5 范例中的 String.prototype.trim(),此处完成依靠 ES 5 范例中的 White Space 中的形貌。该要领完成相对简朴,同时也提醒了一个设想基本知识:向公认的 API 靠齐,完成要领中心后供应要领扩大,遵照该准绳的包含:

  • Preact 与 React
  • Zepto 与 jQuery
  • Lodash 与 Underscore 等

trim() 函数较为简朴明白,而 reduce() 要领的完成与 ES 5 中的 Array.prototype.reduce(callbackfn[,initialValue]) 定义的算法完全相同,更能表现这一准绳,此段不举行解释,进入 ES 5 范例中该函数定义即可对比明白该 Polyfill 的完成要领。

  //\ Line 11
  if (Array.prototype.reduce === undefined)
    Array.prototype.reduce = function(fun) {
      //\ 略
    };

Detect 模块 / User Agent 辨认

Detect 模块用于辨认浏览器平台范例,默许也不处于编译列表中,其代码 src/detect.js 构造构造以下:

//\ Line 5
;(function($){

  //\ 平台侦测逻辑
  function detect(ua, platform){
  }

  //\ 传入 Zepto 及平台环境变量
  detect.call($, navigator.userAgent, navigator.platform)
  // make available to unit tests
  $.__detect = detect

//\ 将全局变量 Zepto 带入,化为参数 '$'
})(Zepto)

平台侦测逻辑 function detect(ua, platform) 内部为一组大的字符串推断逻辑,构成如许乱七八糟的平台推断逻辑,恰是由于一代一代的浏览器大战。 User-Agent 字符串被定义为包含了当前浏览器(范例称号 User Agent)信息的 HTTP 头部标识,用于使服务器能够依据平台完成浏览器检测并下发差别的原始代码用于衬着。由于浏览器假装等种种缘由,UA 现实并不可托,因而关于它的侦测相称难题,罕见 UA 能够从 List of User Agents 页面内查询到。

Zepto 没有默许编译该模块,以及应用该模块推断后供应平台相干逻辑的重要缘由在于其设想准绳:20% 的代码完成 jQuery 中心 80% 的功用。此处,也引出了代码完成的另一个基本准绳:面向功用/API 范例,先功用掩盖再文雅降级。以供应一个罕见的 Browser Compatibility Matrix 为例,依据完成规格测试前端产出在差别平台的可用性,再供应降级计划或 Polyfill 以满足更多的用户需求。

    原文作者:cyw0ng
    原文地址: https://segmentfault.com/a/1190000017062690
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞