欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

jQuery.prototype.init选择器构造函数源码思路分析

程序员文章站 2022-04-15 10:46:15
一、思路分析总结 概要: jquery的核心思想可以简单概括为“查询和操作dom”,今天主要是分析一下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:

. 代码如下:


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 = $('<p></p>', { 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代码:

. 代码如下:


<p class="main">
<h2 class="title">主内容标题</h2>
<p>主标题</p>
</p>
<p class="sub">
<h2 class="title">次内容标题</h2>
<p>次标题</p>
</p>


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]为空的单标签元素(如:<p><p>)且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 );
}
}