jquery源码学习-2-选择器
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>jquery1.0.1</title> </head> <body> <div id="box">div#box</div> <script src="./jquery.1.0.2.js"></script> <script> console.log($('<a>')) console.log($('#box')) /* init 0: a length: 1 __proto__: Object init 0: div#box context: document length: 1 selector: "#box" __proto__: Object */ console.log($(document)) /* init 0: document context: document length: 1 */ </script> </body> </html>
(function(root){ var testExp = /^\s*(<[\w\W]+>)[^>]*$/; var rejectExp = /^<(\w+)\s*\/?>(?:<\/\l>|)$/; var version = '1.0.1' var jQuery = function(selector,context){ return new jQuery.prototype.init(selector,context) } jQuery.fn = jQuery.prototype = { length:0, //merge中使用。。。??? jQuery:version, selector:'', //调用时传过来的参数,可以使对象,函数,字符串 init:function(selector,context){ //context 限定查询的范围 context = context || document; var match,elem,index= 0; if(!selector){ //$() | $(undefine) | $(null) | $(fasle) return this; } if( typeof selector === 'string' ){ //两个用途,1、创建DOM节点,,2、查询DOM节点 if( selector.charAt(0) ==='<' && selector.charAt(selector.length-1) === '>' && selector.length>=3 ){ //selector是html字符串 match = [selector] //存入html字符串 } if( match ){ //创建DOM节点 //合并数组 object(有length属性) [context.createElement(parse[1])](DOM节点) jQuery.merge(this, jQuery.parseHTML(selector,context)); }else{ //查询DOM节点 elem = document.querySelectorAll(selector); //类数组 var elems = Array.prototype.slice.call(elem); //转换成数组 this.length = elems.length; for(; index<elems.length; index++){ this[index] = elems[index]; } this.context = context; //给jquery的实例对象扩展context属性 this.selector = selector; ///给jquery的实例对象扩展selector属性 } }else if( selector.nodeType ){ //有nodeType,则传过来的是个对象 this|document|window this.context = this[0] = selector; this.length = 1; return this; }else if( typeof selector == 'function'){ //函数 //??? } }, } jQuery.fn.init.prototype = jQuery.fn; //浅拷贝,深拷贝(第一个参数为true) jQuery.fn.extend = jQuery.extend = function(){ //根据参数内容和个数来实现 var target = arguments[0] || {} var length = arguments.length; var i = 1; var deep = false; var option,name,copy,src,copyIsArray,clone; if( typeof target === 'boolean'){ //判断是否有深浅拷贝的标识,如果是boolean类型 deep = target ; //deel复制标识 target = arguments[1]; //将要拷贝的对象赋值为第二个参数 i = 2; //要遍历的参数从第二个开始 } if( typeof target !== 'object'){ //第一个参数不是对象,就给他赋值为空对象 target = {} } if(length === i){ //判断参数个数 ,如果参数个数为1,则是为 jquey/jquery实例对象 扩展对象, target = this; //this只想对象的引用 i-- } //浅拷贝 for(; i<length; i++){ //如果参数个数不为1,直接从第二个参数开始,若为0,则从第一个开始,产生无用消耗 if( (option = arguments[i]) != null){ for(name in option){ copy = option[name] src = target[name]; if(deep && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))){ //深拷贝 if(copyIsArray){ copyIsArray = false; clone = src && jQuery.isArray(src)? src :[]; }else{ clone = src && jQuery.isPlainObject(src)? src :{}; } target[name] = jQuery.extend(deep,clone,copy) }else if(copy != undefined){ //浅拷贝 target[name] = copy; } } } } return target } jQuery.extend({ isPlainObject:function(obj){ return toString.call(obj) === '[object Object]' }, isArray:function(obj){ return toString.call(obj) === '[object Aarray]' }, /** * @param {*} first -- jquery的实例对象 => this * @param {*} second -- 数组的引用 => [dom] */ merge:function(first, second){ //合并数组 var l = second.length, //1 i = first.length, //0 j = 0; if( typeof l == 'number'){ for(; j <l; j++){ //给first添加数组,dom节点的创建存储 first[i++] = second[j] //0:'a' console.log(first); } }else{ } first.length = i; return first; }, parseHTML:function(data, context ){ //解析html元素 if(!data ||typeof data != 'string'){ return null; } //过滤掉 '<a>' => 'a' var parse = rejectExp.exec(data); //用正则提取标签名 return [context.createElement(parse[1])]; //创建DOM元素,将元素存入到数组中,将数组返回去 } }) root.$ = root.jQuery = jQuery })(this)