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 相关文章推荐
JQuery自定义事件的应用 JQuery最佳实践
Aug 01 Javascript
给超链接添加特效鼠标移动展示提示信息且随鼠标移动
Oct 17 Javascript
asp.net刷新本页面的六种方法总结
Jan 07 Javascript
Node调试工具JSHint的安装及配置教程
May 27 Javascript
JavaScript-RegExp对象只能使用一次问题解决方法
Jun 23 Javascript
简述Jquery与DOM对象
Jul 10 Javascript
两种JavaScript的AES加密方式(可与Java相互加解密)
Aug 02 Javascript
VC调用javascript的几种方法(推荐)
Aug 09 Javascript
Angular4学习教程之DOM属性绑定详解
Jan 04 Javascript
微信小程序动态添加view组件的实例代码
May 23 Javascript
vue实现用户长时间不操作自动退出登录功能的实现代码
Jul 23 Javascript
Vue vee-validate插件的简单使用
Jun 22 Vue.js
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 最大运行时间 max_execution_time修改方法
2010/03/08 PHP
php无序树实现方法
2015/07/28 PHP
php封装好的人民币数值转中文大写类
2015/12/20 PHP
twig模板常用语句实例小结
2016/02/04 PHP
验证坐标在某坐标区域内php代码
2016/10/08 PHP
PHP读取XML文件的方法实例总结【DOMDocument及simplexml方法】
2019/09/10 PHP
通过修改referer下载文件的方法
2008/05/11 Javascript
JavaScript 事件记录使用说明
2009/10/20 Javascript
Firefox下提示illegal character并出现乱码的原因
2010/03/25 Javascript
jquery 学习之一 对象访问
2010/11/23 Javascript
jQuery插件的写法分享
2013/06/12 Javascript
Javascript实现滚动图片新闻的实例代码
2013/11/27 Javascript
jquery基础教程之deferred对象使用方法
2014/01/22 Javascript
如何防止JavaScript自动插入分号
2015/11/05 Javascript
jQuery实现的分子运动小球碰撞效果
2016/01/27 Javascript
jQuery插件FusionCharts实现的3D帕累托图效果示例【附demo源码】
2017/03/25 jQuery
vue如何引用其他组件(css和js)
2017/04/13 Javascript
微信小程序获取用户openId的实现方法
2017/05/23 Javascript
vue权限路由实现的方法示例总结
2018/07/29 Javascript
vue-router路由懒加载的实现(解决vue项目首次加载慢)
2018/08/28 Javascript
解决vue移动端适配问题
2018/12/12 Javascript
封装微信小程序http拦截器过程解析
2019/08/13 Javascript
阿望教你用vue写扫雷小游戏
2020/01/20 Javascript
Python中的生成器和yield详细介绍
2015/01/09 Python
使用rpclib进行Python网络编程时的注释问题
2015/05/06 Python
python脚本设置超时机制系统时间的方法
2016/02/21 Python
不要用强制方法杀掉python线程
2017/02/26 Python
使用python爬虫实现网络股票信息爬取的demo
2018/01/05 Python
在python中利用numpy求解多项式以及多项式拟合的方法
2019/07/03 Python
django admin.py 外键,反向查询的实例
2019/07/26 Python
python 字典套字典或列表的示例
2019/12/16 Python
Overload和Override的区别
2012/09/02 面试题
寒假家长评语大全
2014/04/16 职场文书
会计求职信
2014/05/29 职场文书
2015年小学教科研工作总结
2015/07/20 职场文书
python基础之匿名函数详解
2021/04/21 Python