美文网首页
polyfill源码阅读(二)HTML

polyfill源码阅读(二)HTML

作者: Atlas_lili | 来源:发表于2019-04-09 16:48 被阅读0次

html部分主要是修改不同浏览器的API的怪异行为。

(function(global) {
  'use strict';
  if (!('window' in global && 'document' in global))
    return;
    // do something
})(self)

一段自执行函数的模块封装,内加执行环境的判断确保后面代码的安全。

document.head

返回当前文档中的 <head> 元素。如果有多个 <head> 元素,则返回第一个。

PC兼容性.png
移动端兼容性
if (!('head' in document))
    document.head = document.getElementsByTagName('head')[0];

这样的写法很容易想到。

对H5元素的支持

[
    'abbr', 'article', 'aside', 'audio', 'bdi', 'canvas', 'data', 'datalist',
    'details', 'dialog', 'figcaption', 'figure', 'footer', 'header', 'hgroup',
    'main', 'mark', 'meter', 'nav', 'output', 'picture', 'progress', 'section',
    'summary', 'template', 'time', 'video'].forEach(function(tag) {
     document.createElement(tag);
   });

确保解释不出的新标签解析为行内标签。

HTMLElement.dataset

读写节点的自定义属性

PC兼容性.png
值得注意的是:移动端都不支持!
if (!('dataset' in document.createElement('span')) &&
      'Element' in global && Element.prototype && Object.defineProperty) {
    Object.defineProperty(Element.prototype, 'dataset', { get: function() {
      var result = Object.create(null);
      for (var i = 0; i < this.attributes.length; ++i) {
        var attr = this.attributes[i];
        if (attr.specified && attr.name.substring(0, 5) === 'data-') {
          (function(element, name) {
            var prop = name.replace(/-([a-z])/g, function(m, p) {
              return p.toUpperCase();
            });
            result[prop] = element.getAttribute('data-' + name); // Read-only, for IE8-
            Object.defineProperty(result, prop, {
              get: function() {
                return element.getAttribute('data-' + name);
              },
              set: function(value) {
                element.setAttribute('data-' + name, value);
              }});
          }(this, attr.name.substring(5)));
        }
      }
      return result;
    }});
  }

实际上是利用get和set监听了每一个自定义属性的改变,对应到节点上。

atob()和btoa()

window.atob()对用base-64编码过的字符串进行解码。window.btoa() 方法来编码一个可能在传输过程中出现问题的数据。

兼容性.png
(function() {
    if ('atob' in global && 'btoa' in global)
      return;
    var B64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    function atob(input) {
      // do something
    };
    function btoa(input) {
      // do something
    };
    global.atob = atob;
    global.btoa = btoa;
  }());

atob()

function atob(input) {
      input = String(input);
      var position = 0,
          output = [],
          buffer = 0, bits = 0, n;

      input = input.replace(/\s/g, '');
      if ((input.length % 4) === 0) { input = input.replace(/=+$/, ''); }
      if ((input.length % 4) === 1) { throw Error("InvalidCharacterError"); }
      if (/[^+/0-9A-Za-z]/.test(input)) { throw Error("InvalidCharacterError"); }

      while (position < input.length) {
        n = B64_ALPHABET.indexOf(input.charAt(position));
        buffer = (buffer << 6) | n;
        bits += 6;

        if (bits === 24) {
          output.push(String.fromCharCode((buffer >> 16) & 0xFF));
          output.push(String.fromCharCode((buffer >>  8) & 0xFF));
          output.push(String.fromCharCode(buffer & 0xFF));
          bits = 0;
          buffer = 0;
        }
        position += 1;
      }

      if (bits === 12) {
        buffer = buffer >> 4;
        output.push(String.fromCharCode(buffer & 0xFF));
      } else if (bits === 18) {
        buffer = buffer >> 2;
        output.push(String.fromCharCode((buffer >> 8) & 0xFF));
        output.push(String.fromCharCode(buffer & 0xFF));
      }

      return output.join('');
    };

这就要说到BASE64解码过程了,解码时四个字符为一组(每个字符索引0-63,共24位二进制),每个字符按顺序转成BASE64数组对应索引的二进制形式,此时将二十四位二进制八位一组,对应ASCII码可译出三个字符。=为占位,可以忽略。

function btoa(input) {
    input = String(input);
    var position = 0,
      out = [],
      o1, o2, o3,
      e1, e2, e3, e4;
    if (/[^\x00-\xFF]/.test(input)) { throw Error("InvalidCharacterError"); }
    while (position < input.length) {
      o1 = input.charCodeAt(position++);
      o2 = input.charCodeAt(position++);
      o3 = input.charCodeAt(position++);
      // 111111 112222 222233 333333
      e1 = o1 >> 2;
      e2 = ((o1 & 0x3) << 4) | (o2 >> 4);
      e3 = ((o2 & 0xf) << 2) | (o3 >> 6);
      e4 = o3 & 0x3f;
      if (position === input.length + 2) {
        e3 = 64;
        e4 = 64;
      }
      else if (position === input.length + 1) {
        e4 = 64;
      }
      out.push(B64_ALPHABET.charAt(e1),
        B64_ALPHABET.charAt(e2),
        B64_ALPHABET.charAt(e3),
        B64_ALPHABET.charAt(e4));
    }
    return out.join('');
  };

编码的过程,将字符串三个一组依次对应ASCII码转成二进制串(位数不足补0,缺整6的倍数补=),六位二进制一组,对应BASE64数组索引的字母,拼接成编码字符串。

相关文章

  • polyfill源码阅读(二)HTML

    html部分主要是修改不同浏览器的API的怪异行为。 一段自执行函数的模块封装,内加执行环境的判断确保后面代码的安...

  • Polyfill源码阅读

    Polyfill源码阅读 自己作为前端大半年的新手,刚刚红皮书看完,开始看一些比较浅层次的源码,来加深对于规范的理...

  • polyfill源码阅读(五)dom二

    CustomEvent 创建一个自定义事件。 用了一个createEvent定义事件,initCustomEven...

  • polyfill源码阅读(三)XHR

    XHR部分主要处理对IE行为的兼容。 上来就是一段对传入环境的判断,看起来比较熟悉。 首先对ajax依赖的XHR对...

  • vue学习1

    Vue源码学习 基本函数 bind的polyfill方案 once方法 generateComponentTrac...

  • polyfill源码阅读(一)ES5

    这是蚂蚁面试官推荐我读的一个项目的源码,可能因为代码结构比较简单,主要解决兼容性,对于前端小白来说比较有用吧。 O...

  • Polyfill简介

    1.什么是Polyfill? Polyfill是一个js库,主要抚平不同浏览器之间对js实现的差异。比如,html...

  • iOS 系统源码及第三方源码总结

    1.系统源码总结 RunTime源码阅读(一)之weakRunTime源码阅读(二)关联对象RunTime源码阅读...

  • Promise-Polyfill源码解析(2)

    在上篇文章Promise-Polyfill源码解析(1)详细分析了Promise构造函数部分的源码,本篇我们继续分...

  • polyfill源码阅读(四)cssom和dom一

    cssom Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。...

网友评论

      本文标题:polyfill源码阅读(二)HTML

      本文链接:https://www.haomeiwen.com/subject/tvgviqtx.html