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

在我的上一篇随笔里面分析了jQuery的构造函数,jQuery对象中有一个原型方法init才是是真正的构造函数,通过init的原型对象跟jQuery的原型对象保持引用关系使得init的实例可以正常调用jQuery的原型方法,就好像是jQuery的实例一样。下面就来看看init这个幕后的构造函数是怎么写的:

init: function( selector, context, rootjQuery ) {

...

}

可以看到这个方法接受3个参数,其前两个参数是jQuery方法传递过来的

var jQuery = function( selector, context ) {

// The jQuery object is actually just the init constructor ‘enhanced‘

return new jQuery.fn.init( selector, context, rootjQuery );

},

Selector原则上可以输入任意值,但并不是所有值都是有意义的,只有undefined、DOM 元素、字符串、函数、jQuery 对象、普通 JavaScript 对象这几种类型是有效的,这个参数是通常是填写的但是不填写也不会报错

console.log($());

//[constructor: function, init: function, selector: "", jquery: "1.7.1", size: function…]

Context作为执行上下文或者叫执行范围可以不传入,或者传入 DOM 元素、jQuery 对象、普通 JavaScript 对象之一

参数 rootjQuery:包含了 document 对象的 jQuery 对象,用于 document.getElementById() 查找失败、selector 是选择器表达式且未指定 context、selector 是函数的情况,其实就是$(document)。

下面根据参数的不同分为12种情况逐个讨论

1.selector 可以转换为false

// Handle $(""), $(null), or $(undefined)

if ( !selector ) {

return this;

}

源码中的注释已经写得很清楚了,当是这三种情况时直接return不进行任何处理

2.参数 selector 是 DOM 元素

例如: $(document)这种写法

// Handle $(DOMElement)

if ( selector.nodeType ) {

this.context = this[0] = selector;

this.length = 1;

return this;

}

只要是dom元素肯定有节点类型,然后把这个节点变成jquery对象的第一个元素并且赋值给上下文context,length属性是jQuery的原型属性默认为0

// The default length of a jQuery object is 0

length: 0,

这里有了一个元素之后就把length属性修改为1。return this 操作使得函数执行后的结果依然是jQuery对象这样就可以实现类似$(document).each()这样的链式调用了。最终得到的类似这样的{0:document,context:document,length:1....}对象,其实所有的情况最后都会变成这种形式的对象,除了jQuery原型属性和方法之外就是获取的dom节点并且按照阿拉伯数字依次排列,所以我们可以使用$(selector)[0]的形式代替$(selector).get(0)来获取dom对象。例如:

<!doctype html>

<html>

   <head>

      <title></title>

   </head>

   <body>

       <div></div>

       <div></div>

       <div></div>

   </body>

   <script src=‘jquery-1.7.1.js‘></script>

   <script>

     console.log($(‘div‘));

/*[div, div, div, prevObject: jQuery.fn.jQuery.init[1], context: document, selector: "div", constructor: function, init: function…]

0: div
1: div
2: div
context: document
length: 3
prevObject: jQuery.fn.jQuery.init[1]__proto__: jQuery[0]
selector: "div"
.
*/
   </script>

</html>

3.参数是特殊的字符串“body”

由于body元素在一个文档对象中只有一个所以单独列出来处理

// The body element only exists once, optimize finding it

if ( selector === "body" && !context && document.body ) {

this.context = document;

this[0] = document.body;

this.selector = selector;

this.length = 1;

return this;

}

这里有3个条件必须同时满足,第二个必须没有上下文的条件我也不是太理解,$(‘body’,document)这样的看起来很正常的写法也会被这种情况“忽视”

 console.log($(‘body‘,document));

 /*

 jQuery.fn.jQuery.init[1]

0: body

context: document

length: 1

prevObject: jQuery.fn.jQuery.init[1]

selector: "body"

__proto__: jQuery[0]

*/

虽然和$(‘body‘)的结果是一样的,但是却被当做两种情况来看待,可能是因为body只有一个上下文只能是document没有必要添加吧,否则又要判断上下文是不是document。第三个条件是保证document.body必须存在,那么什么情况下会前两个情况满足document.body又不存在呢?首先就是js代码先于html代码加载时会出现这个是初学者经常会犯的错误,通常我们要写成:

$(function(){...})

或者

$(document).ready(function(){...})

其实这两个是一样的调取的是一个方法,dom加载这一块以后在分析。对此我们可以做个测试html代码如下:

<!doctype html>

<html>

   <head>

      <title></title>

        <script src=‘jquery-1.7.1.js‘></script>

      <script> 

              $(‘body‘)

   </script>

   </head>

   <body>

       <div></div>

       <div></div>

       <div></div>

   </body>

</html>

  

然后再jQuery源代码里面输出selector、context和document.body

console.log(selector+context+document.body);

// The body element only exists once, optimize finding it

if ( selector === "body" && !context && document.body ) {

this.context = document;

this[0] = document.body;

this.selector = selector;

this.length = 1;

return this;

}

虽然我们只写了一个其实执行了四次,只有最后一次才是是我们调用后的结果,最后一次的结果是bodyundefinednull这个时候前两个就是满足的但是最后一个是null。回想起第一篇jQuery总体架构架构里面undefined会被重新,那么document.body会不会被重写为null呢?当我尝试在代码中修改时就会报错看来是不会的,那这个条件就是预防没有加载html就执行的情况吧

第四种是除了上述的字符串情况之外的其他字符串,情况比较多放在下一篇吧。

时间: 2024-10-13 17:12:11

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

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

分析完了字符串情况剩下的就不多了. 5.参数selector是函数 这个就是很容易想到了,首先说一下dom加载.我们通常在head里面写脚本的时候需要等待文档加载在进行处理,js是这么写的 1 window.onload=function(){ 2 your code... 3 } 但是这样是需要等待所有资源都加载完毕才会执行,如果页面有很多图片的话就会加载的很慢.dom2级呢有一个加载完成事件DOMContentLoad比较好用,这个事件是会在html文档结构加载完毕触发.比如说这个页面有10

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分析(3) - jQuery.fn.init

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

四.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

jQuery源码 框架分析

每一个框架都有一个核心,所有的结构都是基于这个核心之上,结构建立好了之后,剩下的就是功能的堆砌. jQuery的核心就是从HTML文档中匹配元素并对其操作. 就跟一座大楼一样,让我们一步一步了解这座大厦的基石和结构. 1.构造函数 2.链式语法 3.选择器 4.扩展性  一.构造函数 我们知道类是面向对象编程的一个重要概念,它是对事物的最高抽象,它是一个模型.通过实例化一个类,我们可以创建一个实例. javascript本身没有类的概念,只有原型prototype,prototype是什么呢?它

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

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

jQuery源代码阅读之一——jQuery总体结构及jQuery构造函数

一.jQuery总体架构 jQuery作为一款强大的js库,由以下模块构成: (function(window,undefined){ var jQuery=function(selector,context){ //... }; //工具方法utilities //回调函数 callbacks //异步队列 Defered Object //浏览器功能测试 Support //数据缓存 Data //队列 Queue //属性操作 Attributes //事件系统 Events //选择器

Jquery源码中的Javascript基础知识(四)— jQuery.fn.init方法

$() 即调用了jQuery.fn.init方法 jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context, rootjQuery ); } 下面是init方法代码: 1 init: function( selector, context, rootjQuery ) { 2 var match, elem; 3 if ( !selector ) { 4 return this; 5