上篇已經講解了zepto.init()的幾種狀況,這篇就繼續記錄這幾種狀況下的具體分析.css
既然是反向分析,那咱們先看看這句話的代碼;html
if (!selector) return zepto.Z()
java
這裏的返回值爲zepto.Z();
那咱們繼續往上找zepto.Z()函數node
zepto.Z = function(dom, selector) { return new Z(dom, selector) }
這個函數仍然擁有一個返回值,Z函數的實例,一樣的道理,咱們繼續去找Z()
;正則表達式
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 || '' }
根據以上代碼能夠分析出,當沒有參數時,會獲得一個length:0,selector:''
的對象.
數組
一樣的,咱們先看看這句話的代碼dom
else if (typeof selector == 'string') { selector = selector.trim() }
if (selector[0] == '<' && fragmentRE.test(selector)) dom = zepto.fragment(selector, RegExp.$1, context), selector = null
這裏有兩個知識點:
1 fragmentRE.test(selector)
函數
這裏的fragmentRE是Zepto函數在以前定義的一段正則; ```java //<div>erfwef</div> 取出<div> fragmentRE = /^\s*<(\w+|!)[^>]*>/, ```
2 zepto.fragment(selector, RegExp.$1, context)
* RegExp.$1
RegExp.$1爲RegExp的一個屬性,指的是與正則表達式匹配的第一個 子匹配(以括號爲標誌)字符串;
例子:
java var r= /^(\d{4})-(\d{1,2})-(\d{1,2})$/; r.exec('1985-10-15'); s1=RegExp.$1; s2=RegExp.$2; s3=RegExp.$3; alert(s1+" "+s2+" "+s3)//結果爲1985 10 15
* zepto.fragment()
函數this
```java //對應上面的代碼,這裏第一個參數是selector,就是咱們在寫代碼時的$('xxx')中的xxx,name爲RegExp.$1,即正則匹配的第一個()裏的東西,就是標籤元素,例如 div p h1等,properties爲執行環境. zepto.fragment = function(html, name, properties) { var dom, nodes, container // singleTagRE仍爲以前定義的變量,singleTagRE = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, 匹配值以下截圖 //如html傳入值爲<p></p>,匹配singleTagRE,則建立<p></p>,並調用$('<p></p>') if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1)) //若是不匹配 if (!dom) { //這是一段修復代碼,將<div/>之類的不正常的代碼修復成<div></div>;具體的下面再講解 if (html.replace) html = html.replace(tagExpanderRE, "<$1></$2>") //若是沒有標籤名,,給他一個標籤,fragmentRE = /^\s*<(\w+|!)[^>]*>/, if (name === undefined) name = fragmentRE.test(html) && RegExp.$1 //containers = {tr': document.createElement('tbody'),tbody': table, 'thead': table, 'tfoot': table,td': tableRow, 'th': tableRow,'*': document.createElement('div')}, //若是name值不在container範圍內,則標籤名爲div if (!(name in containers)) name = '*' //建立容器 container = containers[name] //把html片斷放入到容器中 container.innerHTML = '' + html //這裏調用了$.each();一會再詳細講解,這裏是涉及到哪一個函數我就去解析哪一個函數,雖然看起來比較亂,可是符合我本身的邏輯線路. //emptyArray = [], slice = emptyArray.slice,因此這裏的slice.call即爲Array.prototype.slice.call(),能將具備length屬性的對象轉成數組; dom = $.each(slice.call(container.childNodes), function(){ //刪除 container.removeChild(this) }) } if (isPlainObject(properties)) { nodes = $(dom) $.each(properties, function(key, value) { if (methodAttributes.indexOf(key) > -1) nodes[key](value) else nodes.attr(key, value) }) } return dom
}
```prototype
以上代碼出現了singleTagRE
else if (context !== undefined) return $(context).find(selector)
這裏涉及到一個方法find,是$.fn中的方法,以後作統一分析;
else dom = zepto.qsa(document, selector)
zepto.qsa = function(element, selector){ var found, //判斷是否是ID maybeID = selector[0] == '#', //判斷是否是css maybeClass = !maybeID && selector[0] == '.', //看是否是class和id名,若是是,將'#'或者'.'去除,而後賦值給nameOnlt; //不然,直接將值賦值; nameOnly = maybeID || maybeClass ? selector.slice(1) : selector, //simpleSelectorRE = /^[\w-]*$/, //匹配字母數字下劃線和減號的組合; isSimple = simpleSelectorRE.test(nameOnly) //若是有內置getElementById方法,而且是id名; return (element.getElementById && isSimple && maybeID) ? //則返回element.getElementByID(nameOnly) ( (found = element.getElementById(nameOnly)) ? [found] : [] ) : //反之的話,再作一次判斷 //若element不爲元素節點,document,DocumentFragment時;爲空, (element.nodeType !== 1 && element.nodeType !== 9 && element.nodeType !== 11) ? [] : //不然,將節點轉換成數組; slice.call( //這裏是一個三元運算符裏套着另外一個三元運算符; isSimple && !maybeID && element.getElementsByClassName ? //當爲class,則調用element.getElementsByClassName(nameOnly) maybeClass ? element.getElementsByClassName(nameOnly) : //不然調用tagName; element.getElementsByTagName(selector) : //這個不然是最外層的判斷; element.querySelectorAll(selector) ) }
else if (isFunction(selector)) return $(document).ready(selector)
else if (zepto.isZ(selector)) return selector
若是selector爲數組;
java // if (isArray(selector)) dom = compact(selector)
這裏用到了一個compact方法;
java //這裏調用了一個filter方法,是在$.fn內,之後統一分析; //這個函數是去除數組中的null和undefined; function compact(array) { return filter.call(array, function(item){ return item != null }) }
因此當爲數組的時候,去除數組中的null和undefined;
java else if (isObject(selector)) dom = [selector], selector = null
java else if (fragmentRE.test(selector)) dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
有context的時候
else if (context !== undefined) return $(context).find(selector)
沒有context
java else dom = zepto.qsa(document, selector)