jQuery.prototype.init选择器构造函数源码思路分析
一、源码思路分析总结
概要:
jQuery的核心思想可以简单概括为“查询和操作dom”,今天主要是分析一下jQuery.prototype.init选择器构造函数,处理选择器函数中的参数;
这个函数的参数就是jQuery()===$()执行函数中的参数,可以先看我之前写的浅析jQuery基础框架一文,了解基础框架后,再看此文。
思路分析:
以下是几种jQuery的使用情况(用于查询dom),每种情况都返回一个选择器实例(习惯称jQuery对象(一个nodeList对象),该对象包含查询的dom节点):
1、处理 $(""), $(null), $(undefined), $(false)
如果参数为以上非法值,jQuery对象不包含dom节点
2、处理 $(DOMElement)
如果参数为节点元素,jQuery对象包含该参数节点元素,并分别增加属性值为参数节点元素、1的context、length属性和用[]访问jQuery对象中dom节点的用法
例2.1:
3、处理$(HTML字符串)
如果第一个参数为HTML字符串,jQuery对象包含由jQuery.clean函数创建的fragment文档碎片中的childnodes节点
例3.1:
如果第一个参数(HTML字符串)为一个空的单标签,且第二个参数context为一个非空纯对象
例3.2:
4、处理$(#id)
如果第一个参数是一个#加元素id,jQuery对象包含唯一拥有该id的元素节点,
并分别增加属性值为document、参数字符串、1、的context、selector、length属性和用[]访问jQuery对象中dom节点的用法
例4.1:
5、处理$(.className)
如果第一个参数是一个.className,jQuery对象中拥有class名为className的标签元素,并增加一个属性值为参数字符串、document的selector、context属性
实际执行代码为:
6、处理$(.className, context)
如果第一个参数是.className,第二个参数是一个上下文对象(可以是.className(等同于处理$(.className .className)),jQuery对象或dom节点),
jQuery对象包含第二个参数上下文对象中拥有class名为className的后代节点元素,并增加一个context和selector属性
实际执行代码为:
例6.1:
html代码:
JavaScript代码:
7、处理$(fn)
如果第一个参数是fn函数,则调用$(document).ready(fn);
例7.1:
8、处理$(jQuery对象)
如果第一个参数是jQuery对象,上面已经分析过如果在查询dom时,参数是一个#加元素id,返回的jQuery对象会增加一个属性值为参数字符串、document的selector、context属性
例8.1:
那么当出现$($('#container'))该如何处理呢?同样的,返回的jQuery对象同情况5和6处理的情况一样
例8.2:
二、源码注释分析
[ 基于jQuery1.8.3 ]
概要:
jQuery的核心思想可以简单概括为“查询和操作dom”,今天主要是分析一下jQuery.prototype.init选择器构造函数,处理选择器函数中的参数;
这个函数的参数就是jQuery()===$()执行函数中的参数,可以先看我之前写的浅析jQuery基础框架一文,了解基础框架后,再看此文。
思路分析:
以下是几种jQuery的使用情况(用于查询dom),每种情况都返回一个选择器实例(习惯称jQuery对象(一个nodeList对象),该对象包含查询的dom节点):
1、处理 $(""), $(null), $(undefined), $(false)
如果参数为以上非法值,jQuery对象不包含dom节点
2、处理 $(DOMElement)
如果参数为节点元素,jQuery对象包含该参数节点元素,并分别增加属性值为参数节点元素、1的context、length属性和用[]访问jQuery对象中dom节点的用法
例2.1:
代码如下:
var obj = document.getElementById('container'), jq = $(obj); console.log(jq.length); //1 console.log(jq.context); //obj console.log(jq.[0]); //obj
3、处理$(HTML字符串)
如果第一个参数为HTML字符串,jQuery对象包含由jQuery.clean函数创建的fragment文档碎片中的childnodes节点
例3.1:
代码如下:
var jqHTML = $('<h1>文章标题</h1><p>内容</p>'); console.log(jqHTML); //[<h1>,<p>];
如果第一个参数(HTML字符串)为一个空的单标签,且第二个参数context为一个非空纯对象
例3.2:
代码如下:
var jqHTML = $('<div></div>', { class: 'css-class', data-name: 'data-val' }); console.log(jqHTML.attr['class']); //css-class console.log(jqHTML.attr['data-name']); //data-val
4、处理$(#id)
如果第一个参数是一个#加元素id,jQuery对象包含唯一拥有该id的元素节点,
并分别增加属性值为document、参数字符串、1、的context、selector、length属性和用[]访问jQuery对象中dom节点的用法
例4.1:
代码如下:
var jq = $('#container'); console.log(jq.[0]); //包含的dom节点元素 console.log(jq.length); //1 console.log(jq.context); //document console.log(jq.selector); //container
5、处理$(.className)
如果第一个参数是一个.className,jQuery对象中拥有class名为className的标签元素,并增加一个属性值为参数字符串、document的selector、context属性
实际执行代码为:
代码如下:
return jQuery(document).find(className);
6、处理$(.className, context)
如果第一个参数是.className,第二个参数是一个上下文对象(可以是.className(等同于处理$(.className .className)),jQuery对象或dom节点),
jQuery对象包含第二个参数上下文对象中拥有class名为className的后代节点元素,并增加一个context和selector属性
实际执行代码为:
代码如下:
return jQuery(context).find(className);
例6.1:
html代码:
代码如下:
<div class="main"> <h2 class="title">主内容标题</h2> <p>主标题</p> </div> <div class="sub"> <h2 class="title">次内容标题</h2> <p>次标题</p> </div>
JavaScript代码:
代码如下:
var jq, context; context = '.sub'; var jq = $('.title', context); console.log(jq.text()); //次内容标题 console.log(jq.context); //document console.log(jq.selector); //.sub .title context = $('.sub'); var jq = $('.title', context); console.log(jq.text()); //次内容标题 console.log(jq.context); //document console.log(jq.selector); //.sub .title context = $('.sub')[0]; var jq = $('.title', context); console.log(jq.text()); //次内容标题 console.log(jq.context); //className为sub的节点元素 console.log(jq.selector); //.title
7、处理$(fn)
如果第一个参数是fn函数,则调用$(document).ready(fn);
例7.1:
代码如下:
$(function(e){ console.log('DOMContent is loaded'); }) //上面代码等同于: jQuery(document).ready(function(e) { console.log('DOMContent is loaded'); });
8、处理$(jQuery对象)
如果第一个参数是jQuery对象,上面已经分析过如果在查询dom时,参数是一个#加元素id,返回的jQuery对象会增加一个属性值为参数字符串、document的selector、context属性
例8.1:
代码如下:
var jq = $('#container'); console.log(jq.selector); // #container console.log(jq.context); // document
那么当出现$($('#container'))该如何处理呢?同样的,返回的jQuery对象同情况5和6处理的情况一样
例8.2:
代码如下:
var jq2 = $($('#container')); console.log(jq2.selector); // #container console.log(jq2.context); // document
二、源码注释分析
[ 基于jQuery1.8.3 ]
代码如下:
var rootjQuery = $(document), rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/; jQuery.fn = jQuery.prototype = { init: function( selector, context, rootjQuery ) { var match, elem, ret, doc; // Handle $(""), $(null), $(undefined), $(false) if ( !selector ) { return this; } // Handle $(DOMElement) if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; } // Handle HTML strings if ( typeof selector === "string" ) { if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = rquickExpr.exec( selector ); } // Match html or make sure no context is specified for #id // match[1]不为null,则为html字符串,match[2]不为null,则为元素id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) if ( match[1] ) { context = context instanceof jQuery ? context[0] : context; doc = ( context && context.nodeType ? context.ownerDocument || context : document ); // scripts is true for back-compat // selector是由文档碎片中的childnodes组成的数组 selector = jQuery.parseHTML( match[1], doc, true ); // 如果match[1]为空的单标签元素(如:<div><div>)且context为对象字面量 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { // 如果context对象不为空,则将对象中的属性添加到selector数组中仅有的dom节点中 this.attr.call( selector, context, true ); } // merge函数的参数应该为两个数组,目的是将第二个数组中的项合并到第一个数组,而this并不是一个数组, // this是选择器init构造函数的实例对象,该对象继承jQuery.prototype对象中的length属性(默认为0),因此可以理解好merge函数源码 // 将selector中的dom项合并到this对象中,并返回该对象 return jQuery.merge( this, selector ); // HANDLE: $(#id) } else { elem = document.getElementById( match[2] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID // ie6,7和Opera存在此bug,当一个标签name和一个标签id值相等时, // document.getElementById(#id)函数将返回提前出现的标签元素 if ( elem.id !== match[2] ) { // 如果存在以上Bug,则返回由find函数返回的document文档的后代元素集合 return rootjQuery.find( selector ); } // Otherwise, we inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } // HANDLE: $(expr, $(...)) // context不存在或者context为jQuery对象 } else if ( !context || context.jquery ) { return ( context || rootjQuery ).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) // context为className或者dom节点元素 } else { // 等同于jQuery(context).find(selector) return this.constructor( context ).find( selector ); } // 处理$(fn)===$(document).ready(fn) } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } // 处理$(jQuery对象) if ( selector.selector !== undefined ) { this.selector = selector.selector; this.context = selector.context; } // 当第一个参数selector为jQuery对象时,将selector中的dom节点合并到this对象中,并返回this对象 return jQuery.makeArray( selector, this ); } }
相关推荐
83510998 2020-08-08
tthappyer 2020-07-25
tztzyzyz 2020-07-05
87281248 2020-07-04
82244951 2020-06-28
89510194 2020-06-27
牵手白首 2020-06-14
开心就好 2020-06-10
EdwardSiCong 2020-11-23
85477104 2020-11-17
hhanbj 2020-11-17
81427005 2020-11-11
seoppt 2020-09-13
honeyth 2020-09-13
WRITEFORSHARE 2020-09-13
84483065 2020-09-11
momode 2020-09-11
85477104 2020-08-15