jQuery1.8.1的95~289行,关于jQuery的prototype上构造函数init方法的介绍。
一、prototype的赋值与覆盖
首先是给jQuery的原型重新覆盖了对象:
jQuery.fn = jQuery.prototype = {//.......}
而在覆盖的对象中有个constructor属性。需要这样赋值的原因是此处我们是直接覆盖了原型对象,而不是修改他的属性,constructor会在创建时,指向jQuery,因为被覆盖了,所以需要重新指向。比如:
var Fun = function() { // Fun构造函数 this.place = 'earth'; }; Fun.prototype.show = function() { // 添加属性,属于赋值操作 console.log(this.place); }; var fn = new Fun(); console.log(fn.constructor === Fun); // true Fun.prototype = { // 覆盖了原先的prototype show: function() { console.log(this.place); } }; var fn1 = new Fun(); console.log(fn1.constructor === Fun); // false,因为是{}覆盖的,所以指向Object
正是这种原因,这儿对constructor进行了重新的赋值。
二、init函数
该init函数是我们每次使用$(jQuery)时,创建jQuery对象的构造函数。
init: function( selector,context,rootjQuery ) {
init函数带有三个参数,第一个是选择器,可以是id、class或复杂的字符串,也可以是dom对象等。第二个参数是上下文,正常情况下都是document,有些时候,当我们在iframe中使用时,需要对这个context进行赋值。第三个参数是document的jQ对象,在906行:rootjQuery = jQuery(document)。
空值过滤
进入函数内部,首先是过滤了空字符串(””)、null、undefined、false这些值,直接返回this。
dom转化jqdom
紧接着的if用于处理dom,我们都知道,$(dom)这样使用时,我们可以得到这个dom的jQ对象。于是,这儿给new出的实例添加了个0的属性,且值是该dom。并将length置为1。注:这儿的对象是类数组,他的属性值类似于数组的下标,且含有length,但他实质上不是数组,就和函数内部的arguments类似。
过滤了以上的条件后,开始处理字符串。我们想想,平时,我们可以写$(‘#box’)、$(‘.class’)、$(‘#box div’)、$(‘<div></div>’)、$(‘<div>111</div>’)、$(function(){})等。这些方式可以细分为创建元素和查找元素。
处理字符串
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
该方式查找前后都是标签的html字符串,像$(‘<div></div>’)、$(‘<div>111</div>’)这些,而$(‘<div>123’)这种是不会进入if的。if中得到了这样的一个match数组:
match = [ null,selector,null ];
而else中,利用正则的匹配也得到了一个长度是三的类似的数组,
match = rquickExpr.exec( selector ); rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,59行,用来检测html的字符串形式的。正则匹配用到的知识就不展开了
正则匹配完成之后,会对匹配结果进行判断,
if ( match && (match[1] || !context) ) {
当存在match时,且match中第二个元素是true或是false但context上下文不存在时才会走。所以进入该if的有:$(‘<div></div>’)、$(‘<div>111</div>’)、$(‘<div>123’),$(‘#box’)要是能进入if的话,创建时的上下文必须不给赋值。这样一判断之后,是创建元素还是查找元素,大致已经被区分开了。
创建元素
随后使用 if ( match[1] ) { 来区分掉刚才上下文为false的id查找字符串。因此,能够进入if的都是创建元素的字符串。接下来,首先是对context的赋值,保证该context是原生的dom对象,并且对doc变量进行赋值。随后调用jQ的工具方法parseHTML将匹配到的HTML字符串转化为jq对象。如何转化的,到parseHTML定义的地方在叙述。
注:$(‘<div>123’)得到的元素不会带123,是因为正则匹配的时候,match第二个值是<div>,所以创建的时候,只是创建了div元素,并没有赋值。
if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { this.attr.call( selector,true ); }
检测当时单个元素时,且context是一个纯对象时,就系那个context下的属性给到创建的那个元素上。这也就是当我们写$(‘<p></p>’,{‘title’: ‘aaa’,html: ‘abcd’}).appendTo(‘html’)这种方式时,会给新创建的p元素添加两个属性。
再来看下进入else中的$(‘#box’),使用了元素查找的方式,并且也做了浏览器兼容的处理,查找完成之后,便返回了this。
创建元素解决了,下面是查询元素。
元素查找
else if ( !context || context.jquery ) {
当没有上下文时,直接在document的jQ对象下调用find方法。当context存在时,能够进入的条件就是context下含有jQuery属性,比如$(‘.class’,$(‘div#box’))这样的写法就会进入该条件下。
而$(‘.class’,document.getElementById(‘box’))这种的会进入下一个else,执行find操作。
$(function)
当传入function的方式还没有考虑到,当使用$(function() {})时,会调用jQ根对象下的ready方法,也就是文档加载完成后执行。这也就是为什么我们常常说,$(function(){})是$(document).ready(function(){})的一种简写方式。
最后剩下个if判断传入的selector的selector属性:
if ( selector.selector !== undefined ) { this.selector = selector.selector; this.context = selector.context; }
该方式是兼容$(jQ对象)这种方式的,这样也增加了$的容错性。
将所有的情况都考虑一遍,整个init函数就是这种情况:
init: function( selector,rootjQuery ) { if ( !selector ) { // $(""),$(null),$(undefined),$(false) } if ( selector.nodeType ) { // $(DOMElement) } if ( typeof selector === "string" ) { // $('<div>123'),$('<div>123</div>'),$('432<div>123</div>243'),$('#box'),$('#box',document) // $('<div></div>',{title: '123'}),$(document)),$('.class'),$('#box p') if ( match && (match[1] || !context) ) { // $('<div>123'),$('<div></div>',{title: '123'}) if ( match[1] ) { // $('<div>123'),$('432<div>123</div>243') if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { // $('<div></div>',{title: '123'}) } } else { // $('#box') } } else if ( !context || context.jquery ) { // $('#box',$('#box p') } else { // $('#box',document) } } else if ( jQuery.isFunction( selector ) ) { // $(function) } if ( selector.selector !== undefined ) { // $(jQobject) } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。