平时写js,用到选择器是必不可少的,一直用框架的选择器,内部到底是怎么样的呢
(function(){ var doc = document, REG_ID = /^#[\w-]+$/, REG_QUERY = /^(:?#([\w-]+))?\s*([\w-]+|\*)?\.?([\w-]+)?$/; //将封装好的默认函数在进行集中处理,用正则来区分传入的selector function query(selector,content){ var match, ret = [], id, tag, cls ,t; content = tuneContent(content); if(isString(selector)){ selector = trim(selector); //如果传入的是id,那么就直接用封装好的getElementById if(REG_ID.test(selector)){ t = getElementById(selector.slice(1),content); if(t) ret = [t];//返回数组 //exec返回第一个匹配的字符串,和所有分组的反向引用(即正则中括号包裹的部分) }else if((match = REG_QUERY.exec(selector))){ id = match[1]; tag = match[2]; cls = match[3]; //如果获取到的反向引用中有id,那么将content设为根据id获取到的元素, //否则仍旧为tuneContent调整后的值 if(content = id ? getElementById(id,content) : content){ //如果有class if(cls){ //如果没有id并且传入的selector参数中有空格,即排除#id.cls if(!id && selector.indexOf(" ") !== -1){ //那么使用封装好的getElementsByClassName来获取元素 ret = getElementsByClassName(cls,tag,content); }else{ //处理#id.cls 这个selector参数应该表示的是#id并且这个id的className值为cls //那么先根据id取到元素,在判断取到的这个元素的className是否含有cls t = getElementById(id,content); if(t && hacClass(t,cls)){ ret = [t]; } } }else if(tag){//如果有tag //那么直接用原生的getElementsByTagName来获取元素 ret = content.getElementsByTagName(tag); } } } } return ret; } function get(){ return query(selector,content)[0]; } //将content调整到一个合理的值 function tuneContent(content){ //如果content未定义,那么content=doc if(content === undefined){ content = doc; //如果content是个id,那么content=根据id获取到元素 }else if(isString(content) && REG_ID.test(content)){ content = getElementById(content.slice(1),doc); //如果content即不是元素或者不是doc文档类型,那么content=null }else if(content && content.nodeType !== 1 && content.nodeType !==9){ content = null; } return content; } //封装默认的getElementById函数 function getElementById(el,content){ if(content.nodeType !== 9){ content = content.ownerDocument; } return content.getElementById(el); } //封装默认的getElementsByClassName函数(高级浏览器才有这个默认函数) function getElementsByClassName(cls,tag,content){ if(!cls) return; var els = content.getElementsByClassName(cls), ret = els,j=0; //根据传入的tag筛选获取到的元素 if(tag && tag != "*"){ ret = []; for(var i = 0,len = els.length;i<len;i++){ el = els[i]; if(el.tagName == tag.toUpperCase()){ ret[j++] = el; } } } return ret; } //如果不支持getElementsByClassName,则降级使用querySelectorAll, //再不支持,则先根据tag获取到元素,在遍历这些元素,看这些元素的className是否含有传入的className值 if(!doc.getElementsByClassName){ if(doc.querySelectorAll){ getElementsByClassName = function(cls,tag,content){ return content.querySelectorAll((tag ? tag : "") +"." + cls); } }else{ getElementsByClassName = function(cls,tag,content){ var els = content.getElementsByTagName(tag), ret = [],j=0,cls = " "+cls+" "; for(var i = 0,len = els.length;i<len;i++){ var el = els[i],t = el.className; if(t && hasClass(el,cls)){ ret[j++] = el; } } return ret; } } } function isString(str){ return str && typeof str === "string"; } function trim(str){ return str.replace(/(^\s*)|(\s*$)/g,""); } //不支持多个cls同时判断 function hasClass(el,cls){ var cls = " " + cls + " ", elcls = " " + el.className + " "; return elcls.indexOf(cls) > -1; } })();