上篇已经讲解了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)