Zeptoソース分析4-コアモジュール入口


第三篇の末尾の内容を受けて、本編は公式APIを結合してZepto核心に対する分析に入ります.開始は難しいです.いくつかの核心対象の関係を重点的に理解する必要があります.手がかりを見つけることができます.$()とZオブジェクト作成
Zepto Core APIの最初の方法$()は、その公式解釈に従う.
Create a Zepto collection oject by performing a CSS selector、wrapping DOM nodes、or creating elements from an HTML string.
CSSセレクタを使用したり、DOMノードを包装したり、HTMLセグメントからZeptoセットオブジェクトを作成します.ここはコアモジュールの入口であり、src/zepto.jsの中の次のような呼び出しに対応しています.
  //\ Line 231
  $ = function(selector, context) {
    return zepto.init(selector, context);
  };
  
  //\ Line 186
  zepto.init = function(selector, context) {
    //\         
    /*\ 1 */ return zepto.Z();
    /*\ 2 */ return $(context).find(selector);
    /*\ 3 */ return $(document).ready(selector);
    /*\ 4 */ return selector;
    /*\ 5 */ return $(context).find(selector);
    /*\ 6 */ return zepto.Z(dom, selector);
  };
$は、緊縮エントリのzepto.initの別名であり、このような関数伝達により、zepto.initの値パラメータは最大2つとなる.zepto.init関数に入ると、中間の処理の詳細を無視して、最終的な輸出は上記の6つの種類があることに気づき、第1のものは第6のものとZというオブジェクトの作成プロセスに陥り、$.fnオブジェクトはconstructorに向けられ、zepto.Zオブジェクトのプロトタイプが設定されている.ここはZeptoの構造組織方式です.
  //\ Line 172
  zepto.Z = function(dom, selector) {
    return new Z(dom, selector);
  };

  //\ Line 408
  $.fn = {
    constructor: zepto.Z,
    //\ ...
  }
  
  //\ Line 938
  zepto.Z.prototype = Z.prototype = $.fn;
Zeptoコードを読み込んだら、ブラウザで以下のように調整して、Zオブジェクトの生成を初歩的に認識することができます.
//\        Zepto   ,        $.fn
> $().__proto__ === $.fn
true

//\ $        Zepto         ,       Zepto   ,  $.func       
> Object.keys($)
(22) ["extend", "contains", "type", ... ]

//\ $.fn       Zepto         API,         zepto.Z       Z   
> Object.keys($.fn)
(75) ["constructor", "length", "forEach", "reduce", ... ]

//\    Z               $.fn       
> $().hasClass === $.fn.hasClass
true
引き続きデバッグプロセスを行い、Zオブジェクトの本質を分析する:
//\        Z   ,   Chrome        “  ”
> $()
Z [selector: ""]

//\         Array         
> $() instanceof Array
false
> $() instanceof Zepto.zepto.Z
true

//\ Zepto    "    "                        selector    ,                  
> Object.keys($())
(2) ["length", "selector"]
このような「拡張配列」生成の方法は、この非常に簡明な関数であり、ここでは、Zの次の指し示しは、thisオブジェクトである.
  //\ Line 128
  //\ Z     Constructor
  function Z(dom, selector) {
    var i,
      len = dom ? dom.length : 0;
    for (i = 0; i < len; i++) this[i] = dom[i];
    this.length = len;
    this.selector = selector || "";
  }
したがって、構造関数を呼び出してZオブジェクトを生成する方法は、Zに戻ります(2/3/5出口は、あるZオブジェクトの下で動作して生成されたZオブジェクトです.4出口は実際にZオブジェクトが入ってきて、直接に自身に戻ります).Zオブジェクトコンストラクタに読み込まれた2つのパラメータzepto.initdomは、Zeptoにおいても、Zコンストラクタの単純性を保証するための明確な仕様がある.selectorの生成とdomの取得範囲selectorの生成は、以下のいくつかの正規表現とその生成関数domに厳密に依存し、このステップは比較的に難しく、つまり、元のdom構造を対応するZオブジェクトにマッピングする関係である.
    //\ Line 10
    //\         HTML   ,    Group 1 (\w+|!)        ,  : div
    fragmentRE = /^\s*]*>/,
    //\                       , :

/ singleTagRE = /^(?:|)$/, //\ ,Group 1 / Gruop 2 Group 1 tagExpanderRE = /]*)\/>/gi, //\ Line 140 zepto.fragment = function(html, name, properties) { var dom, nodes, container; //\ singleTagRE document , $() if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1)); if (!dom) { //\ replace html if (html.replace) html = html.replace(tagExpanderRE, "$2>"); //\ name , if (name === undefined) name = fragmentRE.test(html) && RegExp.$1; //\ name containers , * if (!(name in containers)) name = "*"; //\ containers , html container = containers[name]; container.innerHTML = "" + html; //\ container , dom Z //\ :https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild dom = $.each(slice.call(container.childNodes), function() { container.removeChild(this); }); } //\ if (isPlainObject(properties)) { //\ dom Z , properties $(dom) nodes = $(dom); $.each(properties, function(key, value) { if (methodAttributes.indexOf(key) > -1) nodes[key](value); else nodes.attr(key, value); }); } //\ dom return dom; };

分析期間のいくつかの疑問:
  • どうしてテスト用の正則が三つありますか?
    次の3つの呼び出し方式の結果が同じであることを保証するために、
    > $.zepto.fragment("
    ") Z [div, selector: ""] > $.zepto.fragment("
    ") Z [div, selector: ""] > $.zepto.fragment("
    ") Z [div, selector: ""]
    • container containers

    containers name innerHTML , , div.

        //\ Line 22
        containers = {
          tr: document.createElement("tbody"),
          tbody: table,
          thead: table,
          tfoot: table,
          td: tableRow,
          th: tableRow,
          "*": document.createElement("div")
        },
  • zepto.fragmentisObject:
  • で3 のパラメータタイプを する は、isPlainObjectだけでなくisPlainObjectを しており、 などを けるために のObjectと される がある は、ここでオブジェクトのプロトタイプを する.
      //\ Line 74
      function isPlainObject(obj) {
        return (
          isObject(obj) &&
          !isWindow(obj) &&
          Object.getPrototypeOf(obj) == Object.prototype
        );
      }
    isObjectは、DOMよりもずっと であり、 のSelectorモジュールを しないと、selectorというブラウザ によってサポートされているセレクタの である.(Zeptoソースコードの のDocument.querySelectorAll()は、モダリティを するために く われています.ここで するselectorは、 にはZオブジェクトのselector です.)selectorの6つの
    のクッションがあって、やっとzepto.initに ることができます.その6つの に するZオブジェクトの または を します.
      zepto.init = function(selector, context) {
        var dom
        
        //\    1:         Falsy  ,           Z   (        )
        //\   : $() / $(undfined)
        if (!selector) return zepto.Z()
        
        //\    selector       
        else if (typeof selector == 'string') {
          
          //\   selector          '")
          //\      6
          if (selector[0] == ' alert("DONE))
        else if (isFunction(selector)) return $(document).ready(selector)
        
        //\    5:           Z          (          )
        //\    JSON.stringify($($('p'))) === JSON.stringify($('p')) 
        else if (zepto.isZ(selector)) return selector
        //\             ,         
        else {
          //\       Selector    ,     Falsy    ,   $([$('div'), $('body')])
          if (isArray(selector)) dom = compact(selector)
          //\        ,     6
          else if (isObject(selector))
            dom = [selector], selector = null
          //\          2/3     
          else if (fragmentRE.test(selector))
            dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
          else if (context !== undefined) return $(context).find(selector)
          else dom = zepto.qsa(document, selector)
        }
        
        //\    6,         dom / selector    Z   (        )
        return zepto.Z(dom, selector)
      }
    この 、zepto.initオブジェクトとZオブジェクトとの の を えることもでき、domはZオブジェクト の Zオブジェクトである.domzepto.initは してこそ、zepto.fragmentが のタイプに ることができることを に することができ、 のタイプの と の 、これもZeptoの である.