您现在的位置: 万盛学电脑网 >> 程序编程 >> 脚本专题 >> javascript >> 正文

jQuery构造函数init参数分析续

作者:佚名    责任编辑:admin    更新时间:2022-06-22

   其实楼主的F和jQuery.fn.init是相等的; 实现功能是和jq一样的, 只是jq的把构造函数放进原型;如果非要说原因,个人理解jq这样写整体结构清晰,先是入口构造函数,紧跟着是原型部分(原型里面init是初始化),但是不好理解;乍一看确实挺绕, 我也是看了好久才明白怎么回事

  如果selector是其他字符串情况就比较多了比较复杂了

  ?

1 2 // Handle HTML strings if ( typeof selector === "string" ) {...}

  开始分不同的情况处理

  ?

1 2 3 4 5 6 7 // Are we dealing with HTML string or an ID? if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = quickExpr.exec( selector ); }

  If里面先判断第一个字符是“<”最后一个字符是“>”并且长度大于3就假设此时的selector是html简单标签 ,比如$(‘

')但是记住仅仅是假设”assume”比如$(‘')这样的也会走这里。然后把match数组修改成[null,selector,null],这里的match是在init函数里面声明的变量,主要是用来作为区分是参数类型的工具稍后在将可能情况列出,下面是源码中声明的四个变量

 

  ?

1 2 init: function( selector, context, rootjQuery ) { var match, elem, ret, doc;

  如果不满足if的条件就会调用一个正则去得到match的结果,quickExpr是jQuery构造函数里面声明的变量

  ?

1 2 3 // A simple way to check for HTML strings or ID strings // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) quickExpr = /^(?:[^#<]*(<[wW]+>)[^>]*$|#([w-]*)$)/,

  这个正则主要是为了区别html字符串和id字符串的,第二个注释中讲到了为了避免基于 location.hash的 XSS 攻击,于是在 quickExpr 中增加了 #(#9521)的意思是我们可以在jQuery官网找到相关解释。

  首先访问http://bugs.jquery.com/然后搜索对应的值即可

  quickExpr.exec( selector )执行的结果可以是一个数组,数组的第一个元素是匹配的元素,剩下的分别是分组匹配的元素,这个正则有两个分组(<[wW]+>)[^>]和([w-]*)一个是标签一个是id值。最终会把结果交给match。下面就来分析下match的各种情况首先单标签不用正则式是 [ null, selector, null ]的形式,下面在代码中证明:

  ?

1 2 3 4 5 6 7 8 9 10 11 12 13 <!doctype html> <html> <head> <title></title> <script src='jquery-1.7.1.js'></script> </head> <body> <div id='div'></div> </body> <script> $('<div>'); </script> </html>

  在html里面我们创建一个jQuery对象然后再init方法里面输出得到的match结果:

  ?

1 2 3 4 5 6 7 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = quickExpr.exec( selector ); } console.log(match); // [null, "<div>", null];

  下面我们修改一下参数改为$(‘#div')然后再看一下结果

   代码如下:

  ["#div", undefined, "div", index: 0, input: "#div"]

  还有一种比较特殊的情况$(‘

123')然后我们再看一下结果

 

  代码如下:

  ["

dewrwe", " ", undefined, index: 0, input: " dewrwe"]

 

  我们可以看到id总是在第三个元素而标签值在第二个元素保存着,对于最后一种情况而言跟$(‘

')是没有什么区别的因为生成dom元素时是不会处理第一个元素的。基于这个结果可以接着来分析下一个判断了。

 

  接下来的会根据match的结果分为三种情况

  ?

1 2 3 4 5 6 7 8 9 10 11 12 13 if ( match && (match[1] || !context) ) {   ...   } else if ( !context || context.jquery ) {   ...   } else {   ...   }

  第一种情况满足的条件是match一定要有值,match[1]就是第二个元素就是保存标签的这个有值或者不存在上下文,但是好像没有id什么事啊?其实不是的通过分析match的结果可以知道第二个元素没有值肯定就是id选择器得到的结果,而id是唯一的,不需要写上下文(其实写了上下文也会正常执行只不过会使用Sizzle而不是在这里处理了跟body是一样的)。好了第一个条件进来的情况就是

  1.标签

  $(‘

') $(‘ 123') $(‘ 23213213 ')...

 

  2.没有上下文的id $(‘#div')

  第一个条件内部又进行了细分:

  ?

1 2 3 4 5 6 7 8 9 10 // HANDLE: $(html) -> $(array) if ( match[1] ) {   ...   // HANDLE: $("#id")   }else{   }

  很显然if是处理标签的else是处理id的,先来看看是怎么处理标签的吧

  ?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 context = context instanceof jQuery ? context[0] : context; doc = ( context ? context.ownerDocument || context : document );   // If a single string is passed in and it's a single tag // just do a createElement and skip the rest ret = rsingleTag.exec( selector );   if ( ret ) {