jQuery初始化
来源:互联网 发布:phpcms 模板使用php 编辑:程序博客网 时间:2024/06/09 18:51
- jQuery(selector, context)构造器
前面介绍了jQuery内部全局变量和构造函数,从正则表达式和核心函数的定义中可以看出,jQuery在框架封装上追求的是简洁、实用。在构造jQuery对象中,同样可以看到jQuery的风格。首先,看下jQuery是如何构造对象?jQuery.fn.init(selector, context, rootjQuery)这个函数具有三个参数,那么jQuery的使用者只能传递两个参数,因为jQuery(seletcor, context)构造器只提供了selector、context这两个形参。从selector、context字面上理解为选择器、上下文。 - jQuery选择器
jQuery的api中选择器提供了五中结构:#id、element、.class、*和selector1,selector2,…,selectorN联合形式。先来看下jQuery.init初始化中源码
jQuery.fn = jQuery.prototype = { // The current version of jQuery being used jquery: core_version, constructor: jQuery, init: function(selector, context, rootjQuery) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) if (!selector) { 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 if (match && (match[1] || !context)) { // HANDLE: $(html) -> $(array) if (match[1]) { context = context instanceof jQuery ? context[0] : context; var aaa = jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, true ) // scripts is true for back-compat jQuery.merge(this, aaa); // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { for (match in context) { // Properties of context are called as methods if possible if (jQuery.isFunction(this[match])) { this[match](context[match]); // ...and otherwise set as attributes } else { this.attr(match, context[match]); } } } return this; // 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) { // Inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } // HANDLE: $(expr, $(...)) } else if (!context || context.jquery) { return (context || rootjQuery).find(selector); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor(context).find(selector); } // HANDLE: $(DOMElement) } else if (selector.nodeType) { this.context = this[0] = selector; this.length = 1; return this; // HANDLE: $(function) // Shortcut for document ready } else if (jQuery.isFunction(selector)) { return rootjQuery.ready(selector); } if (selector.selector !== undefined) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray(selector, this); },... ...
jQuery.prototype.init函数体可以拆分为几个if结构:!selector、typeof selector === “string”和selector.selector !== undefined、selector.nodeType和jQuery.isFunction( selector )。
- !selector
// HANDLE: $(""), $(null), $(undefined), $(false) if (!selector) { return this; }
内容一目了然,就是传入:”“、null、undefined和false形式的选择器时,返回一个空的jQuery对象。
- selector.selector !== undefined
if (selector.selector !== undefined) { this.selector = selector.selector; this.context = selector.context; } //将selector中的属性按数组下标形式组装到this对象属性中,如this[0]、this[1]、this[2]... return jQuery.makeArray(selector, this);
如果选择器是一个对象,并且该selector对象包含属性selector,则将该对象包装成jQuery对象,同时由jQuery.makeArray工具方法返回selector和this属性的[]。
jQuery.extend({ ... ... // results is for internal usage only makeArray: function(arr, results) { var ret = results || []; if (arr != null) { //如果Object(arr)为类数组对象,那么将arr合并到ret返回数组中 if (isArraylike(Object(arr))) { jQuery.merge(ret, typeof arr === "string" ? [arr] : arr); } else { //否则,[].push(arr)直接存入数组中 core_push.call(ret, arr); } } return ret; }, /* * 将数组second合并到first数组中,并返回first,也就是first结构会改变。 */ merge: function(first, second) { var l = second.length, i = first.length, j = 0; if (typeof l === "number") { for (; j < l; j++) { first[i++] = second[j]; } } else { while (second[j] !== undefined) { first[i++] = second[j++]; } } first.length = i; return first; }, ... ...});/** - 判断obj是否为数组的依据是length属性和类型,处理window对象外都可以组装成数组。 - 对于每一个页面都只能有一个window对象。 */function isArraylike(obj) { var length = obj.length, type = jQuery.type(obj); if (jQuery.isWindow(obj)) { return false; } if (obj.nodeType === 1 && length) { return true; } return type === "array" || type !== "function" && (length === 0 || typeof length === "number" && length > 0 && (length - 1) in obj);}
- selector.nodeType
如果选择器为HTMLElement元素,则将该元素包装为jQuery对象,并返回。此时,this[0]属性和this.context都设置为selector,并且this.length为1,也就是说jQuery对象是一个isArraylike检查为true的类数组对象。 - jQuery.isFunction( selector )
如果选择器为函数,则将该函数作为ready事件的绑定函数,也就是document.onload的加载处理器。 - typeof selector === “string”
字符类型的选择器可以分为#id、<*>类型的选择器,同时context有无对元素定位也是不同。所以将该类型的选择器切分为几个分支结构: - 单标签的html(
<input>、 <img>和<link>
等等)
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 ]; // 如果selector是aa<....>这种形式的标签, 则html字符检查正则表达式/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/ } else { // 这个正则表达式可以检查<...>html字符,和#...这种Id字符,并且match匹配只会有两种 [<aa>dd,<aa>,undefined]或[#dd,undefined,dd] match = rquickExpr.exec( selector ); }
<*>*</*>
、#id选择器
// Match html or make sure no context is specified for #id,如果match有匹配结果,则进行处理if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array),如果匹配的是html元素选择器,如<div>、aa<div>、...... if ( match[1] ) { //判断当前Element上下文是否jQuery上下文,如果是则去[0]的元素 context = context instanceof jQuery ? context[0] : context; //返回Element元素数组 var aaa = jQuery.parseHTML(match[1], context && context.nodeType ? context.ownerDocument || context : document, true)//合并aaa到this上下文中 // scripts is true for back-compat jQuery.merge( this, aaa); // HANDLE: $(html, props) if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { for ( match in context ) { // Properties of context are called as methods if possible, if ( jQuery.isFunction( this[ match ] ) ) { this[ match ]( context[ match ] ); // ...and otherwise set as attributes } else { this.attr( match, context[ match ] ); } } } return this; // HANDLE: $(#id),如果选择器是按id来进行,那么调用document原生getElementById来实现 } else { elem = document.getElementById( match[2] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963, //因为在黑莓4.6版本中存在Element节点没有parentNode属性情况,所以这里单独处理 if ( elem && elem.parentNode ) { // Inject the element directly into the jQuery object this.length = 1; this[0] = elem; }//如果元素没有parentNode,那么this对象中就没有元素,而只是一个空的jQuery对象 this.context = document; this.selector = selector; return this; }// Match html or make sure no context is specified for #id,如果match有匹配结果,则进行处理 if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array),如果匹配的是html元素选择器,如<div>、aa<div>、...... if ( match[1] ) { //判断当前Element上下文是否jQuery上下文,如果是则去[0]的元素 context = context instanceof jQuery ? context[0] : context;//返回Element元素数组 var aaa = jQuery.parseHTML(match[1], context && context.nodeType ? context.ownerDocument || context : document, true)//合并aaa到this上下文中 // scripts is true for back-compat jQuery.merge( this, aaa); // HANDLE: $(html, props) if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { for ( match in context ) { // Properties of context are called as methods if possible, if ( jQuery.isFunction( this[ match ] ) ) { this[ match ]( context[ match ] ); // ...and otherwise set as attributes } else { this.attr( match, context[ match ] ); } } }return this;// HANDLE: $(#id),如果选择器是按id来进行,那么调用document原生getElementById来实现} else {elem = document.getElementById( match[2] );// Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963,//因为在黑莓4.6版本中存在Element节点没有parentNode属性情况,所以这里单独处理 if ( elem && elem.parentNode ) { // Inject the element directly into the jQuery object this.length = 1; this[0] = elem; }//如果元素没有parentNode,那么this对象中就没有元素,而只是一个空的jQuery对象 this.context = document; this.selector = selector; return this; }// HANDLE: $(expr, $(...)),如果为selector指定了context(jQuery对象),那么直接调用find方法筛选对象}
这一块包含的内容可以从context有没有进行区分,因为从match = rquickExpr.exec( selector )开始,就像match数组的match[1]有没有值进行判断<div>
和#id选择器。首先!context为真、match[1]为真时document.createElement(*)创建HTMLElement元素,也就是$(<div>
)创建元素。其次!context为真、match[1]为假时document.getElementById(match[2])先获取元素,然后包装成jQuery对象。然后,当!context为真、match为false,也即形如div、.class、parent>child和selector1…这种选择器,由( context || rootjQuery ).find( selector )筛选出符合条件的元素。最后,构造this.constructor( context ).find( selector )jQuery对象,同时查找符合selector条件的元素。
从源码中看到jQuery.prototype原型中修正了constructor构造器,这样做的目的是因为jQuery.prototype原型重新赋值了Object字面量{},那么jQuery的constructor就不在指向本身,而是指向了Object,所以通过人为的给{}添加constructor属性,并让它指向jQuery来修正constructor。
- 结论
从上面看出,jQuery初始化函数init中实现了jQuery选择器selector,对于简单的element、#id和<\w\W+>
形式的元素选择,可以直接包装jQuery对象返回,此外jQuery对象本身是一个类数组的对象,它方招数组下标访问形式this[0]、this[1]… … 和this.length属性,可以for(var)下标遍历,而不只是传统对象{}的foreach遍历。
- Jquery 初始化
- Jquery 初始化
- jQuery初始化
- jQuery初始化select option
- jQuery ztree 初始化失败
- jquery页面初始化
- 20、jQuery页面初始化
- jquery初始化加载
- jquery.dataTables中文初始化
- jquery moblie 初始化
- jQuery初始化select选项
- jQuery datetimepicker初始化
- jQuery页面初始化事件
- Jquery+Handler实现数据初始化
- Jquery+Handler实现数据初始化
- Jquery mobile 初始化参数设置详解
- jquery的初始化的方法
- jquery select2插件初始化时赋多个值
- c++文件保存与读取
- [模板]线性筛素数
- 数据分析(入门篇)-第一章-数据分析那些事儿
- Thinkphp5学习(26)调试和日志
- JustOj1227: 统计单词个数
- jQuery初始化
- python中的单例模式
- SpringBoot非官方教程 | 第十二篇:springboot集成apidoc
- 深入理解JVM(五)——JVM调优 Eclipse调优
- Atcoder ARC 077 E
- 杨辉三角的多解(转载)
- Android自定义控件时的事件处理方法
- ida android incompatible debugger server protocol version is 17,expected 19
- Java之字符流、字符缓冲流