jQuery构造函数init参数分析(三)

分析完了字符串情况剩下的就不多了。

5.参数selector是函数

这个就是很容易想到了,首先说一下dom加载。我们通常在head里面写脚本的时候需要等待文档加载在进行处理,js是这么写的

1 window.onload=function(){
2    your code...
3 }


但是这样是需要等待所有资源都加载完毕才会执行,如果页面有很多图片的话就会加载的很慢。dom2级呢有一个加载完成事件DOMContentLoad比较好用,这个事件是会在html文档结构加载完毕触发。比如说这个页面有10个img元素,只要获取到这些元素而不会在意是否图片被加载进来这样就很好地提高了js加载速度,用法如下:

1  addEventListener("DOMContentLoad", function () {
2      your code
3  }, false); 

遗憾的是ie低版本浏览器并不支持这种写法,首先ie低版本没有addEventListener这个绑定事件的方法,倒是有一个相似方法addEvent但是由于存在很多问题往往不被使用,再者ie低版本没有DOMContentLoad事件。那么针对ie低版本(ie9一下)呢通常用doScroll结合onreadystatechange方法检测。具体可以参考http://www.iefans.net/ie-mofang-domcontentloaded/

说完了回到jQuery,我们使用jQuery时就不用考虑浏览器兼容问题了直接:

1 $(function(){
2    yourcode...
3 })
4
5 //或者
6
7 $(document).ready(function(){
8     yourcode...
9 })

第一种就是我们要讲的情况selector是一个函数,其实jQuery会调ready方法,源码如下:

1 // HANDLE: $(function)
2         // Shortcut for document ready
3         } else if ( jQuery.isFunction( selector ) ) {
4             return rootjQuery.ready( selector );
5         }
rootjQuery之前也已经说过啦就是$(document),最终还是执行的ready方法这就是为什么dom加载的两种写法都可以,关于readdy方法也是会用到之前分析的DOMContentLoad,doScroll,onreadystatechange等只不过会更复杂写以后学到dom加载模块在慢慢分析吧。

6.selector是jQuery对象或者特殊对象

这个种情况应该不多没有人喜欢这样$($(document))写吧,但是如果非要有人这样写jQuery也支持

1 if ( selector.selector !== undefined ) {
2     this.selector = selector.selector;
3     this.context = selector.context;
4 }

如果selector存在selector属性说明就可能是jquery对象,为什么说可能是呢,看下面的例子就明白了

1  console.log($({selector:1}));

当我这样写的时候是不是selector(此时是对象{selector:1})的selector属性存在啊而且最后也会生成结果

[Object, selector: 1, context: undefined, constructor: function, init: function, jquery: "1.7.1"…]
0: Object
context: undefined
length: 1
selector: 1
__proto__: jQuery[0]

这个是对原书作者的修正,并不是只有jQuery对象才在这里处理

如果前面说的所有情况都不符合那么jQuery还有最后一招

return jQuery.makeArray( selector, this );

makeArray方法将类数组对象转换为数组对象。但是在代码内部还有更艰巨的任务就是把一些数组、类数组普通对象等不是jQuery的形式的转换成jQuery形式。这个方法在以后详细分析。到了这里jQuery构造函数init的参数就分析完了大类有7个细分呢有12个分类。用原书一张图总结一下吧

下面是整个init函数1.7.1的源码

  1 init: function( selector, context, rootjQuery ) {
  2         var match, elem, ret, doc;
  3
  4         // Handle $(""), $(null), or $(undefined)
  5         if ( !selector ) {
  6             return this;
  7         }
  8
  9         // Handle $(DOMElement)
 10         if ( selector.nodeType ) {
 11             this.context = this[0] = selector;
 12             this.length = 1;
 13             return this;
 14         }
 15
 16         // The body element only exists once, optimize finding it
 17         if ( selector === "body" && !context && document.body ) {
 18             this.context = document;
 19             this[0] = document.body;
 20             this.selector = selector;
 21             this.length = 1;
 22             return this;
 23         }
 24
 25         // Handle HTML strings
 26         if ( typeof selector === "string" ) {
 27             // Are we dealing with HTML string or an ID?
 28             if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
 29                 // Assume that strings that start and end with <> are HTML and skip the regex check
 30                 match = [ null, selector, null ];
 31
 32             } else {
 33                 match = quickExpr.exec( selector );
 34             }
 35
 36             // Verify a match, and that no context was specified for #id
 37             if ( match && (match[1] || !context) ) {
 38
 39                 // HANDLE: $(html) -> $(array)
 40                 if ( match[1] ) {
 41                     context = context instanceof jQuery ? context[0] : context;
 42                     doc = ( context ? context.ownerDocument || context : document );
 43
 44                     // If a single string is passed in and it‘s a single tag
 45                     // just do a createElement and skip the rest
 46                     ret = rsingleTag.exec( selector );
 47
 48                     if ( ret ) {
 49                         if ( jQuery.isPlainObject( context ) ) {
 50                             selector = [ document.createElement( ret[1] ) ];
 51                             jQuery.fn.attr.call( selector, context, true );
 52
 53                         } else {
 54                             selector = [ doc.createElement( ret[1] ) ];
 55                         }
 56
 57                     } else {
 58                         ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
 59                         selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
 60                     }
 61
 62                     return jQuery.merge( this, selector );
 63
 64                 // HANDLE: $("#id")
 65                 } else {
 66                     elem = document.getElementById( match[2] );
 67
 68                     // Check parentNode to catch when Blackberry 4.6 returns
 69                     // nodes that are no longer in the document #6963
 70                     if ( elem && elem.parentNode ) {
 71                         // Handle the case where IE and Opera return items
 72                         // by name instead of ID
 73                         if ( elem.id !== match[2] ) {
 74                             return rootjQuery.find( selector );
 75                         }
 76
 77                         // Otherwise, we inject the element directly into the jQuery object
 78                         this.length = 1;
 79                         this[0] = elem;
 80                     }
 81
 82                     this.context = document;
 83                     this.selector = selector;
 84                     return this;
 85                 }
 86
 87             // HANDLE: $(expr, $(...))
 88             } else if ( !context || context.jquery ) {
 89                 return ( context || rootjQuery ).find( selector );
 90
 91             // HANDLE: $(expr, context)
 92             // (which is just equivalent to: $(context).find(expr)
 93             } else {
 94                 return this.constructor( context ).find( selector );
 95             }
 96
 97         // HANDLE: $(function)
 98         // Shortcut for document ready
 99         } else if ( jQuery.isFunction( selector ) ) {
100             return rootjQuery.ready( selector );
101         }
102
103         if ( selector.selector !== undefined ) {
104             this.selector = selector.selector;
105             this.context = selector.context;
106         }
107
108         return jQuery.makeArray( selector, this );
109     },
时间: 2024-10-13 10:46:10

jQuery构造函数init参数分析(三)的相关文章

jQuery构造函数init参数分析(二)

接着上一篇随笔讨论. 如果selector是其他字符串情况就比较多了比较复杂了 // Handle HTML strings if ( typeof selector === "string" ) {...} 开始分不同的情况处理 // Are we dealing with HTML string or an ID? if ( selector.charAt(0) === "<" && selector.charAt( selector.le

jQuery构造函数init参数分析(一)

在我的上一篇随笔里面分析了jQuery的构造函数,jQuery对象中有一个原型方法init才是是真正的构造函数,通过init的原型对象跟jQuery的原型对象保持引用关系使得init的实例可以正常调用jQuery的原型方法,就好像是jQuery的实例一样.下面就来看看init这个幕后的构造函数是怎么写的: init: function( selector, context, rootjQuery ) { ... } 可以看到这个方法接受3个参数,其前两个参数是jQuery方法传递过来的 var

jQuery分析(3) - jQuery.fn.init

jQuery分析(3) - jQuery.fn.init 1.前言 上一篇jQuery分析(2)中了解了jQuery库的骨架实现原理,这就好比摇滚音乐,摇滚音乐不是某种音乐他就像一个音乐盒子,里面包含了各种不同的摇滚风格(山地.朋克.乡村.流行.硬摇.金属.迷幻等).那么上一篇只是大致了解了jQuery的基本形状,从这篇文章开始会深入jQuery库的各种函数,深入详细的去了解他,那将值得慢慢探索,发现新的神奇好玩的东西. 2.辅助函数 在jQuery.fn.init方法里面使用到了一些jQuer

jquery源码笔记(三): jquery.prototype的一些方法 和属性 init

jquery.fn = jquery.prototype = { 添加实例属性和方法, jquery: 版本, constructor: 修正指向问题 init(): 初始化 和 参数管理 selector:存储选择字符串 length: this 对象的长度 toArray(): 转数组 get(): 转原生集合 pushStack(): jquery 对象入栈 each()  :  便利集合 ready():DOM加载的接口 slice(): 集合的截取 first(): 集合的第一项 la

四.jQuery源码解析之jQuery.fn.init()的参数解析

从return new jQuery.fn.init( selector, context, rootjQuery )中可以看出 参数selector和context是来自我们在调用jQuery方法时传过来的.那么selector和context都有哪些可能. 对于表格中的4~9行中的可能做具体分析. 如果selector是字符串,则首先检测是html代码还是#id. 126行的if语句:以"<"开头,以">"结尾,且长度>=3.则假设额这个是HT

jquery构造函数分析

jquery是面向对象的写法也有构造函数,每次调用jquery方法是就会实例化一个jqeury对象,但是jQuery的写法却非常高明值得我们学习. js虽然不是面向对象的语言,却又很多面向对象的写法,这里推荐大家看一下图灵的<javascript高级程序设计>中的面向对象的程序设计部分.在众多方法中比较常见的写法是构造加原型方式,下面举例: var Person=function(name,age){    this.name=name;    this.age=age; } Person.p

Android中自定义样式与View的构造函数中的第三个参数defStyle的意义

零.序 系统自带的View可以在xml中配置属性,对于写的好的Custom View同样可以在xml中配置属性,为了使自定义的View的属性可以在xml中配置,需要以下4个步骤: 通过<declare-styleable>为自定义View添加属性 在xml中为相应的属性声明属性值 在运行时(一般为构造函数)获取属性值 将获取到的属性值应用到View 怎么将获取到的属性值应用到View就不用说了,自己定义的属性什么用处自己肯定是清楚的,所以接下来看一下前三点. 一.自定义Style 通过<

[转]Android中自定义样式与View的构造函数中的第三个参数defStyle的意义

转自:http://www.cnblogs.com/angeldevil/p/3479431.html Android中自定义样式与View的构造函数中的第三个参数defStyle的意义 零.序 一.自定义Style 二.在XML中为属性声明属性值 1. 在layout中定义属性 2. 设置Style 3. 通过Theme指定 三.在运行时获取属性值 1. View的第三个构造函数的第三个参数defStyle 2. obtailStyledAttributes 3. Example 四.结论与代

jQuery选择器源码分析和easyui核心分析

写在选择器源码分析之前 这里指对1.7.2版本的源码分析,更高版本添加了更多代码. 整个jQuery的代码是写在一个(function(window, undefined){})(window);这样一个闭包里.请思考,为什么要这样做? 将其写在一个闭包函数里,并传入window直接运行的好处有三: 1,统一命名空间,防止变量的污染:  2,将window作为参数传入函数,在函数里调用window的时候,就不用再去找外层的对象,可以提高效率 : 3,undefined并不是javascript的