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 相关文章推荐
通过ifame指向的页面高度调整iframe的高度
Oct 05 Javascript
Mootools 1.2教程 设置和获取样式表属性
Sep 15 Javascript
jQuery的deferred对象使用详解
Aug 20 Javascript
在微信、支付宝、百度钱包实现点击返回按钮关闭当前页面和窗口的方法
Aug 05 Javascript
微信小程序开发之麦克风动画 帧动画 放大 淡出
Apr 18 Javascript
基于vue2.0实现的级联选择器
Jun 09 Javascript
用户管理的设计_jquery的ajax实现二级联动效果
Jul 13 jQuery
详解基于Node.js的微信JS-SDK后端接口实现代码
Jul 15 Javascript
JavaScript 中的 this 简单规则
Sep 19 Javascript
微信jssdk逻辑在vue中的运用详解
Nov 14 Javascript
vue-cli3+typescript新建一个项目的思路分析
Aug 06 Javascript
js实现限定区域范围拖拉拽效果
Nov 20 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项目的方法
2006/10/09 PHP
提升PHP执行速度全攻略(下)
2006/10/09 PHP
谈谈你对Zend SAPIs(Zend SAPI Internals)的理解
2015/11/10 PHP
适合PHP初学者阅读的4本经典书籍
2016/09/23 PHP
实例讲解PHP中使用命名空间
2019/01/27 PHP
js 点击页面其他地方关闭弹出层(示例代码)
2013/12/24 Javascript
Egret引擎开发指南之运行项目
2014/09/03 Javascript
JavaScript中的全局对象介绍
2015/01/01 Javascript
AngularJS内置指令
2015/02/04 Javascript
浅谈javascript实现八大排序
2015/04/27 Javascript
使用jspdf生成pdf报表
2015/07/03 Javascript
jquery实现适用于门户站的导航下拉菜单效果代码
2015/08/24 Javascript
深入学习JavaScript对象
2015/10/13 Javascript
jQuery实现控制文字内容溢出用省略号(…)表示的方法
2016/02/26 Javascript
jQuery Easyui使用(二)之可折叠面板动态加载无效果的解决方法
2016/08/17 Javascript
jQuery插件fullPage.js实现全屏滚动效果
2016/12/02 Javascript
angular+webpack2实战例子
2017/05/23 Javascript
javascript 作用于作用域链的详解
2017/09/27 Javascript
Vue 实时监听窗口变化 windowresize的两种方法
2018/11/06 Javascript
Vue实现一个图片懒加载插件
2019/03/11 Javascript
JavaScript工具库之Lodash详解
2019/06/15 Javascript
解决layui 三级联动下拉框更新时回显的问题
2019/09/03 Javascript
利用JS代码自动删除稿件的普通弹幕功能
2019/09/20 Javascript
讲解Python中fileno()方法的使用
2015/05/24 Python
python读取与写入csv格式文件的示例代码
2017/12/16 Python
python 字典中取值的两种方法小结
2018/08/02 Python
python 顺时针打印矩阵的超简洁代码
2018/11/14 Python
Python3 中作为一等对象的函数解析
2019/12/11 Python
使用python-cv2实现视频的分解与合成的示例代码
2020/10/26 Python
利用css3画个同心圆示例代码
2017/07/03 HTML / CSS
茵宝(Umbro)英国官方商店:英国足球服装生产商
2016/12/29 全球购物
Jacadi Paris英国官网:法国童装品牌
2019/08/09 全球购物
最畅销的视频游戏享受高达90%的折扣:CDKeys
2020/02/10 全球购物
医院办公室主任职责
2013/12/29 职场文书
父母对孩子说的话
2014/04/12 职场文书
《莫泊桑拜师》教学反思
2016/02/22 职场文书