Home > Article > Web Front-end > jQuery constructor init parameter analysis continued_jquery
If the selector is another string, the situation will be more complicated
// Handle HTML strings if ( typeof selector === "string" ) {...}
Start to deal with different situations
// 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 it is first judged that the first character is "1e9addd705b05bcb0a3507e0fe23a965" and the length is greater than 3, it is assumed that the selector at this time is a simple html tag, such as $('dc6dce4a544fdca2df29d5ac0ea9906b') but Remember just to assume that an "assume" like $('d0a5801618bdd08d8316acfb7836b840') will go here. Then modify the match array to [null, selector, null]. The match here is a variable declared in the init function. It is mainly used as a tool to distinguish parameter types. The possible situations will be listed later. The following is the source code. Four variables declared
init: function( selector, context, rootjQuery ) { var match, elem, ret, doc;
If the if condition is not met, a regular expression will be called to get the match result. quickExpr is a variable declared in the jQuery constructor
// A simple way to check for HTML strings or ID strings // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
This regular rule is mainly to distinguish html strings and id strings. The second comment mentions that in order to avoid XSS attacks based on location.hash, # (#9521) is added to quickExpr, which means we Related explanations can be found on the jQuery official website.
First visit http://bugs.jquery.com/ and then search for the corresponding value
The execution result of quickExpr.exec(selector) can be an array. The first element of the array is the matching element, and the remaining elements are grouped matching elements. This regular expression has two groups (67507ba398404e60698e004702128b72)[^>] and ([w-]*) are labels and id values. The result will eventually be given to match. Let’s analyze the various situations of match. First, a single label without regular expression is in the form of [null, selector, null], which is proved in the code below:
<!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>
In html we create a jQuery object and then output the match result in the init method:
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];
Let’s modify the parameters to $(‘#div’) and then take a look at the results
There is also a special case $(‘dc6dce4a544fdca2df29d5ac0ea9906b123') and then let’s take a look at the result
We can see that the id is always in the third element and the tag value is saved in the second element. For the last case, there is no difference from $('dc6dce4a544fdca2df29d5ac0ea9906b') because it generates When using dom elements, the first element will not be processed. Based on this result, we can proceed to analyze the next judgment.
The following will be divided into three situations based on the match results
if ( match && (match[1] || !context) ) { ... } else if ( !context || context.jquery ) { ... } else { ... }
The condition that is met in the first case is that match must have a value. Match[1] means that the second element is the one that saves the label. It has a value or does not have a context, but it seems that there is no ID. What's the matter? In fact, it is not the case. By analyzing the match results, we can know that the second element with no value must be the result obtained by the id selector, and the id is unique, and there is no need to write a context (in fact, if the context is written, it will execute normally, but Sizzle will be used instead. It is not processed here the same as body). Okay, the first condition comes in is
1. Tag
$(‘dc6dce4a544fdca2df29d5ac0ea9906b') $(‘dc6dce4a544fdca2df29d5ac0ea9906b123') $(‘dc6dce4a544fdca2df29d5ac0ea9906b2321321316b28748ea4df4d9c2150843fecfba68')...
2. ID without context $(‘#div’)
The first condition is further subdivided internally:
// HANDLE: $(html) -> $(array) if ( match[1] ) { ... // HANDLE: $("#id") }else{ }
Obviously if is used to process tags and else is used to process ids. Let’s first take a look at how tags are processed
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 ) { if ( jQuery.isPlainObject( context ) ) { selector = [ document.createElement( ret[1] ) ]; jQuery.fn.attr.call( selector, context, true ); } else { selector = [ doc.createElement( ret[1] ) ]; } } else { ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; } return jQuery.merge( this, selector);
First correct the value of context. If it is a jQuery object, turn it into a dom element using the subscript method. This principle has been mentioned before, and then the doc variable is processed. If the context does not exist, assign the document value to doc. If it exists and has the ownerDocument attribute, it is a dom element. This value is still document. If it is not a dom element, such as an ordinary js object, then assign this object to the doc variable. Immediately afterwards, another regular judgment was performed on the selector. This regular rule was also declared in the jQuery constructor for the purpose of judging single tags, such as dc6dce4a544fdca2df29d5ac0ea9906b
然后把结果交给ret变量,基于ret的值又进行划分按照单标签和复杂标签分开处理ret值存在那就是匹配到了单标签然后再根据context是不是普通对象又分为两种情况isPlainObject是检测是不是普通对象的方法,如果是普通对象,就利用js原生方法createElement传入标签创建元素并放在一个数组里面,之所以这样是为了以后跟jquery对象合并方便,然后把数组赋值给selector,后采用对象冒充的方法调用attr方法,这里attr居然有3个参数,而平常我们使用的api里面是两个参数,其实jQuery中有很多类似的情况,同样的方法有着对内对外两个接口。第二个参数就是对象形式的上下文,因为attr可以像
这给我们的其实就是我们以后可以$(‘dc6dce4a544fdca2df29d5ac0ea9906b',{id:'div'})这样写了也是支持的。如果不是对象就直接创建元素不考虑属性。还是把创建的元素放在数组里面。如果ret没有值那就是复杂的标签了比如$(‘dc6dce4a544fdca2df29d5ac0ea9906b23116b28748ea4df4d9c2150843fecfba68')这样的这个时候原生的js就搞不定啦需要调取另外一个方法jQuery.buildFragment来处理,这个方法实现以后在学习吧,总之最后都会创建dom元素。最后返回合并后的结果
不像之前的return this这里是返回merge执行后的结果其实他的任务就是把放在数组里面的创建好的的dom元素合并到jquery元素中去,最终变成{0:div,length:1...}这样的对象形式。这样的话简标签情况就处理完毕。
然后else里面处理的是id的情况
elem = document.getElementById( match[2] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id !== match[2] ) { return rootjQuery.find( selector ); } // Otherwise, we inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this;
很简单直接调用原生js的id选择器但是有一些系统会出现bug
注释说的很清楚黑莓系统,就是元素已经不存在了但是依然能够匹配得到所以再加上父节点,不存在的元素肯定没有父节点的。还有一种情况就是ie和opera浏览器会出现按name值匹配的情况所以在做了一个判断
if ( elem.id !== match[2] ) {
如果真的不幸出现了那就不能使用原生方法而是用find方法也就是使用sizzle引擎了,在大多数正常情况下就直接将获取到的元素放到this里面就可以啦然后修改下context的值。Ok终于把第一个大分支分析完了。然后再看根据match的第二个分支
else if ( !context || context.jquery ) { return ( context || rootjQuery ).find( selector ); }
这里是如果没有上下文或者上下文是jquery对象的时候这个比较简单就是直接用find方法了rootjQuery 就是$(document)
最后字符串的情况上面都不属于的话
This.constructor就是jQuery其实还是使用find方法。
以上所述就是本文的全部内容了,希望大家能够喜欢。