为了账号安全,请及时绑定邮箱和手机立即绑定

jQuery乱谈

标签:
JQuery

 昨天说到了jQuery()的实现,还差一处理HTML字符串的部分没有分析完,今天继续。 

if ( typeof selector === "string" ) {             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 = rquickExpr.exec( selector );             }             // Match html or make sure no context is specified for #id             if ( match && (match[1] || !context) ) {                 // HANDLE: $(html) -> $(array)                 if ( match[1] ) {                     context = context instanceof jQuery ? context[0] : context;                     doc = ( context && context.nodeType ? context.ownerDocument || context : document );                     // scripts is true for back-compat                     selector = jQuery.parseHTML( match[1], doc, true );                     if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {                         this.attr.call( selector, context, true );                     }                     return jQuery.merge( this, selector );                 // HANDLE: $(#id)                 } else {                     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;                 }             // HANDLE: $(expr, $(...))             } else if ( !context || context.jquery ) {                 return ( context || rootjQuery ).find( selector );             // HANDLE: $(expr, context)             // (which is just equivalent to: $(context).find(expr)             } else {                 return this.constructor( context ).find( selector );             }         }

       

  下面我们来一段一段分析:

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 = rquickExpr.exec( selector );   }

   

  selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3这一句用于判断selector字符串是否由"<"开始,">"结尾,而且selector字符串的长度不小于3.就是类似于:$('<p id="test">My <em>new</em> text</p>')这样的情况。如果selector是html标签组成的话,直接match   = [ null, selector, null ];而不用正则检查。否则的话需要match = rquickExpr.exec( selector );。rquickExpr变量是在前面定义的一个正则式字面量:rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/ 。这段正则式只是一种检查HTML字符串的简便方式,优先检测#id,防止XSS通过location.hash攻击,利用检查正则表达式HTML字符串还是元素ID字符串。match   = rquickExpr.exec( selector )这一句把字符串中的匹配正则表达式的文本保存到match数组里。这里用到了我们前面提到的正则表达式quickExpr,match其实是一个数组,第0个元素是与正则表达式相匹配的文本,第1个元素是与正则表达式的第1个子表达式相匹配的文本(如果有的话),第2个元素是第2个子表达式相匹配的文本(如果有的话),第3个元素是第3个子表达式相匹配的文本(如果有的话),这里就是元素的ID,不包含#。

  注:XSS攻击请参看:http://baike.baidu.com/view/2161269.htm; exec()方法请参看:http://www.w3school.com.cn/js/jsref_exec_regexp.asp

  后面的一部分我将以注释的形式解释:      

           /**

        * 正则表达式匹配到了内容,并且 match[1]不为空,或者context为空。

        * match[1]不为空的时候selector是HTML字符串,也就是你可以用$("xland")把对象包装成jQuery对象        

        * context为空的时候selector是页面元素ID

        */

      if ( match && (match[1] || !context) ) {                 // 处理$(html) -> $(array),选择器为html字符串                 if ( match[1] ) {                     context = context instanceof jQuery ? context[0] : context; // 不好意思,这句话我也不理解
            /**
              *  ownerDocument属性返回节点所属的根元素。下面的JS语句保证了上下文(作用域)为根节点
              *
                      */                     doc = ( context && context.nodeType ? context.ownerDocument || context : document );

 

            /**
               * jQuery.parseHTML方法接受三个参数 (data, context, scripts)。data表示HTML字符串;            
                       * context表示是作用域,默认是document,可选;scripts
                       * 是一个boolean值,如果是true的话,就会把HTML字符串里面的脚本也正确解析

 

             *
              */

 

            selector = jQuery.parseHTML( match[1], doc, true );                     if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {                         this.attr.call( selector, context, true );                     }                     return jQuery.merge( this, selector );                 // 选择器为ID,处理形如$("#first")                 } else {                     elem = document.getElementById( match[2] ); // match[2]得到ID的值如:first                     if ( elem && elem.parentNode ) {                         if ( elem.id !== match[2] ) {                             return rootjQuery.find( selector ); // 找到元素                         }                         // 否则直接把元素插入到爆jquery对象                         this.length = 1;                         this[0] = elem;                     }                     this.context = document;                     this.selector = selector;                     return this;                 }             // 处理 形如 $("div .container")的表达式字符串             } else if ( !context || context.jquery ) {                 return ( context || rootjQuery ).find( selector );             // 处理 形如 $("div .container",$('#asd'))的表达式字符串,
            // 相当于$(context).find(expr) ,就是在context上下文中查找
       } else {

 

           return this.constructor( context ).find( selector );
      }

       

  jQuery核心函数分析完毕,感觉还是有很多不满意的地方,慢慢改正吧。

--------------------------------------------添加---------------------------------------------------

  jQuery核心函数里面涉及到了merge()、find()函数。我简单解释一下这俩货吧,先说merge():

 

merge: function( first, second ) {         var l = second.length,             i = first.length,             j = 0;          if ( typeof l === "number" ) {             for ( ; j < l; j++ ) {                 first[ i++ ] = second[ j ];             }          } else {             while ( second[j] !== undefined ) {                 first[ i++ ] = second[ j++ ];             }         }          first.length = i;          return first;     }

       

 

  该方法用于合并两个jQuery对象(因为jQuery对象中有length属性)或者数组内容到第一个对象或数组。使用方法为:jQuery.merge( first, second )。其中first数组是用来合并的数组或jQuery对象,元素是从第二数组或jQuery对象加进来的;second数组或jQuery对象合并到第一,保持不变。内部代码比较简单,主要是判断提供的第二个参数是jQuery对象(因为jQuery对象中有length属性)还是数组。其中:

if ( typeof l === "number" ) {             for ( ; j < l; j++ ) {                 first[ i++ ] = second[ j ];             }          }

   

  当第二个参数的length属性是number类型时,直接循环遍历把第二个参数的每一项添加到第一个参数的后面。接着:

else {             while ( second[j] !== undefined ) {                 first[ i++ ] = second[ j++ ];             }         }

   

  当第二个参数的length属性不是number类型时,循环把第二个参数的每一项添加到第一个参数的后面,一直到第二个参数的一项为undefined,也就是没有定义时结束。

 

  find()方法代码如下:

find: function( selector ) {         var i, l, length, n, r, ret,             self = this;         // 处理jQuery对象或DOM元素         if ( typeof selector !== "string" ) {             return jQuery( selector ).filter(function() {                 for ( i = 0, l = self.length; i < l; i++ ) {                     if ( jQuery.contains( self[ i ], this ) ) {                         return true;                     }                 }             });         }         // 把DOM元素集合加入到jQuery堆栈中         ret = this.pushStack( "", "find", selector );         //  处理选择器字符串,循环把选择的元素添加到堆栈         for ( i = 0, l = this.length; i < l; i++ ) {             length = ret.length;             jQuery.find( selector, this[i], ret );              if ( i > 0 ) {                 // Make sure that the results are unique                 for ( n = length; n < ret.length; n++ ) {                     for ( r = 0; r < length; r++ ) {                         if ( ret[r] === ret[n] ) {                             ret.splice(n--, 1);                             break;                         }                     }                 }             }         }          return ret;     }

       

  该方法可以获得当前元素匹配集合中每个元素的后代,选择性筛选的选择器。使用方法如下:


  如果一个jQuery对象表示一个DOM元素的集合, .find()方法允许我们能够通过搜索DOM树中的这些元素的后代元素从匹配的元素构造一个新的jQuery象。find()children()方法是相似的,但后者只是旅行的DOM树向下一个层级(就是只查找子元素,而不是后代元素)。该方法选择性地接受同一类型选择表达,我们可以传递给$()函数。如果紧随兄弟匹配选择器,它在新建成的jQuery对象中留下;否则,它被排除在外。

 

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消