jQuery构造函数init参数分析


Posted in Javascript onMay 13, 2015

在我的上一篇随笔里面分析了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就执行的情况吧

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

以上所述就是本文的全部内容了,希望大家能够喜欢。

Javascript 相关文章推荐
javascript[js]获取url参数的代码
Oct 17 Javascript
JQuery 学习笔记 选择器之四
Jul 23 Javascript
基于pthread_create,readlink,getpid等函数的学习与总结
Jul 17 Javascript
让网页跳转到指定位置的jquery代码非书签
Sep 06 Javascript
js设置document.domain实现跨域的注意点分析
May 21 Javascript
BootStrap 超链接变按钮的实现方法
Sep 25 Javascript
ES6教程之for循环和Map,Set用法分析
Apr 10 Javascript
微信小程序支付之c#后台实现方法
Oct 19 Javascript
Vue中render方法的使用详解
Jan 26 Javascript
基于vue.js组件实现分页效果
Dec 29 Javascript
微信小程序实现的绘制table表格功能示例
Apr 26 Javascript
微信小程序中使用 async/await的方法实例分析
May 06 Javascript
CSS+JS实现点击文字弹出定时自动关闭DIV层菜单的方法
May 12 #Javascript
JavaScript实现DIV层拖动及动态增加新层的方法
May 12 #Javascript
js实现带按钮的上下滚动效果
May 12 #Javascript
js验证上传图片的方法
May 12 #Javascript
js中setTimeout()与clearTimeout()用法实例浅析
May 12 #Javascript
js实现一个链接打开两个链接地址的方法
May 12 #Javascript
js实现鼠标经过表格行变色的方法
May 12 #Javascript
You might like
php.ini中的php-5.2.0配置指令详解
2008/03/27 PHP
php生成图片验证码的实例讲解
2015/08/03 PHP
Smarty变量用法详解
2016/05/11 PHP
Java 正则表达式学习总结和一些小例子
2012/09/13 Javascript
关于JS中的闭包浅谈
2013/08/23 Javascript
javascript记录文本框内文字个数检测文字个数变化
2014/10/14 Javascript
jQuery实现图片与文字描述左右滑动自动切换的方法
2015/07/27 Javascript
用headjs来管理和加载js 提高网站加载速度
2016/11/29 Javascript
JS实现复制功能
2017/03/01 Javascript
关于HTTP传输中gzip压缩的秘密探索分析
2018/01/12 Javascript
详解vue.js根据不同环境(正式、测试)打包到不同目录
2018/07/13 Javascript
基于vue中对鼠标划过事件的处理方式详解
2018/08/22 Javascript
微信小程序性能优化之checkSession的使用
2019/03/06 Javascript
小程序和web画三角形实现解析
2019/09/02 Javascript
vue transition 在子组件中失效的解决
2019/11/12 Javascript
详解Vue3.0 + TypeScript + Vite初体验
2021/02/22 Vue.js
[01:10:27]DOTA2-DPC中国联赛正赛 SAG vs XG BO3 第二场 3月5日
2021/03/11 DOTA
python中的多重继承实例讲解
2014/09/28 Python
python常规方法实现数组的全排列
2015/03/17 Python
Python反爬虫技术之防止IP地址被封杀的讲解
2019/01/09 Python
Python使用pydub库对mp3与wav格式进行互转的方法
2019/01/10 Python
CSS3 icon font完全指南(CSS3 font 会取代icon图标)
2013/01/06 HTML / CSS
自荐信包含哪些内容
2013/10/30 职场文书
父亲生日宴会答谢词
2014/01/10 职场文书
《小池塘》教学反思
2014/02/28 职场文书
责任担保书范文
2014/05/21 职场文书
软件工程毕业生自荐信
2014/07/04 职场文书
公司人事专员岗位职责
2014/08/11 职场文书
简单通用的简历自我评价
2014/09/21 职场文书
毕业生评语大全
2015/01/04 职场文书
cf战队宣传语
2015/07/13 职场文书
高中生军训感言
2015/08/01 职场文书
python图片灰度化处理的几种方法
2021/06/23 Python
SpringCloud之@FeignClient()注解的使用方式
2021/09/25 Java/Android
java协程框架quasar和kotlin中的协程对比分析
2022/02/24 Java/Android
「我的青春恋爱物语果然有问题。-妄言录-」第20卷封面公开
2022/03/21 日漫