jQuery 원본 분석의 init 방법

8410 단어
jQuery 함수 소스는 다음과 같습니다.
주의: 이런 문법에 따라 마지막으로 되돌아오는 것은 init 대상 유형이어야 한다. 왜 결과는 jQuery 유형일까. 여기에 원형 체인에 대한 지식을 사용했다. init.prototype = jQuery.fn;그래서 jQuery의 원형을 init의 원형으로 설정합니다.
또한 원본 코드에서 대상의 글자 양의 형식을 사용하여 jQuery의 원형에 값을 부여하면 jQuery 함수의 constructor 속성이 덮어쓰이기 때문에 수동으로 수정해야 합니다.예를 들면 다음과 같습니다.
4
	jQuery = function( selector, context ) {
		// The jQuery object is actually just the init constructor 'enhanced'
		// Need init if jQuery is called (just allow error to be thrown if not included)
		return new jQuery.fn.init( selector, context );
	}
jQuery에서 init 함수 소스 분석:
4
  constructor        ,constructor: jQuery         
    function A(){}
    //        A constructor      ,      new A().constructor  function object(){[native code]}
    //  jQuery          ,    constructor      !
    A.prototype={
      name:"xxx",
      sex:"female",
      constructor:A
    }
요약:
첫째, 먼저 전송된 첫 번째 매개 변수인selector가string 유형인지 아닌지를 판단한다.string 유형이 아니라면 아래의'2, 3, 4'로 가라. 그렇지 않으면'1, 2, 3'으로 가라.
1, HTML 탭이나 id 선택기를 만드는지 판단합니다. 만약에 HTML 탭을 만들면parse HTML 방법을 사용해서 DOM 그룹을 가져오고 이 그룹을 JSON 대상this에 봉인합니다. 동시에 만들 때 두 번째 파라미터는 하나의 대상이 될 수 있습니다. 이때 대상에 jQuery의 동명 방법이 있으면 직접 호출하세요!(merge 첫 번째 파라미터는 JSON 상황) id 선택기라면 getElementById를 호출해서 대상을 가져오고this에 봉인합니다!
2, 두 번째 인자 context가 존재하지 않거나 동시에 대상이 존재한다고 판단하면 이 대상을 jQuery 대상으로 봉인하고 이 대상의find 방법을 호출합니다!(class 등 선택기는 최종 호출find 방법)
둘째, 만약에 selector가DOM이라면,DOM을this[0] 위에 봉하여 이 jQuery 대상을 되돌려줍니다!(원본 코드의this는 jQuery 대상입니다. 이것은 구조 함수 내부의this이기 때문입니다.) 셋째,selector가 함수라면 $(document)를 직접 호출합니다.ready () 그리고 함수를 ready 함수의 매개 변수로 실행합니다!
넷째, 만약 전송된selector가 jQuery 대상이라면 매개 변수의 jQuery 대상의 모든 정보를 새로 되돌아오는 대상에 봉합합니다!
먼저 정규 표현식의 내용을 읽는 것을 권장합니다.
사례 1:
4
  init = jQuery.fn.init = function( selector, context ) {
		var match, elem;
		// HANDLE: $(""), $(null), $(undefined), $(false)
		//  return this        init  !
		if ( !selector ) {
			return this;
		}
		// Handle HTML strings
		if ( typeof selector === "string" ) {
		//id   ,class       else
			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 {
			//$("<li>hello").appendTo("ul")          <li></li> $("<li/>").appendTo("ul")  !
			//var rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/
			match = rquickExpr.exec( selector );
			//  $("#div1") $("<div>hello")
			//matched=null//$(".box"),$("div"),$("#div1 div.box")
			//matched=["#div1,null,'div1'"]//  $("#div1")
			//matched=["<li>hello",'<li>',null]//  $("<li>hello")
			}
			//     :$("<li></li>")          !  $("<li>hello")        !
			//id           ,  matched[1] false,  context     ,     id           !
			// $("#div1"),  id    !
			// Match html or make sure no context is specified for #id
			if ( match && (match[1] || !context) ) {
				// HANDLE: $(html) -> $(array)
				if ( match[1] ) {
		//            ?   $("<li>",document)        document,   iframe,   contentWindow.document!
				//     document!
				//  context   document      document,  context $(document)         document!
					context = context instanceof jQuery ? context[0] : context;
					//$("<li>1</li><li>2</li>")         this={0:'li',1:'li',length:2}
					//      DOM    !    parseHTML   !parseHTML        false
		//  parseHTML     script  (   script        ,       script  !)true      script  !
					// scripts is true for back-compat
					// Intentionally let the error be thrown if parseHTML is not present
		//      DOM        JSON   ? merge  !merge      JSON    !       ,length    !
					//   this  new init        !
					jQuery.merge( this, jQuery.parseHTML(
						match[1],
						context && context.nodeType ? context.ownerDocument || context : document,
						true
					) );
					// HANDLE: $(html, props)
					//var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
					//$("<li>",{tile:"abcd",html:'abcn'})
					//          , <li>   <li></li>    $("<li></li><li></li>",{})  !
					//isPlainObject            !
					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
						for ( match in context ) {
							// Properties of context are called as methods if possible
							//     html      ,      html,     this.html("abcn")
							//      jQuery      css      !
							if ( jQuery.isFunction( this[ match ] ) ) {
								this[ match ]( context[ match ] );
							// ...and otherwise set as attributes
							} else {
								this.attr( match, context[ match ] );
							}
						}
					}
					return this;
               //     id    ,        !
			   ////matched=["#div1,null,'div1'"]//  $("#div1")
				// HANDLE: $(#id)
				} else {
					elem = document.getElementById( match[2] );
                     //      4.6      ,             ,      
					 //   parentNode,                   !
					// 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\
						// IE  Opera    ,     name     ,   id!
						//    :rootjQuery = jQuery( document );
						if ( elem.id !== match[2] ) {
							return rootjQuery.find( selector );
						}
                         //Jquery      JSON      ,  length     !
						//       constructor,length   !
						// Otherwise, we inject the element directly into the jQuery object
						this.length = 1;
						this[0] = elem;
					}
					//id          document!
					this.context = document;
					//   jQuery       selector  ,  $("#test")     "#test"   !
					this.selector = selector;
					return this;
				}
             //   id                  !
			// HANDLE: $(expr, $(...))
			//                  jQuery  !        find          !
			// $("li",$("ul"))
			} else if ( !context || context.jquery ) {
				return ( context || rootjQuery ).find( selector );
			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)
			//       jQuery  ,           jQuery      find  
			//this.constructor=jQuery
			} else {
				return this.constructor( context ).find( selector );
			}

		// HANDLE: $(DOMElement)
		//    :$(this),$(document)
		//       jQuery  ,   selector  string   !
		} else if ( selector.nodeType ) {
		//   JSON  0     !
			this.context = this[0] = selector;
			this.length = 1;
			return this;
		// HANDLE: $(function)
		// Shortcut for document ready
		//rootjQuery = jQuery( document );
		//        :$(function(){})      ,       $(document).ready(function(){})
		//  selecot function,      $(document).ready(function(){}),          $(document).ready undfined  
		//   jQuery            !
		} else if ( jQuery.isFunction( selector ) ) {
			return typeof rootjQuery.ready !== "undefined" ?
				rootjQuery.ready( selector ) 
				// Execute immediately if ready is not present
				selector( jQuery );
		}
       //       :$($("#div1"))       $("#div1")
	    //jQuery   selector  !DOM   nodeType  !
		if ( selector.selector !== undefined ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}
          //  makeArray                   JSON  ,           JSON!
		return jQuery.makeArray( selector, this );
	};
이 경우 탭을 만들고 두 번째 인자인 isPlainObject가true로 되돌아오지만 var rsingleTag= (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);정규 표현식은 통과할 수 없습니다. 결국 jQuery는 아무것도 하지 않습니다!
사례 2:
4
$("<div></div><div></div>",{html:'abcn'}).appendTo($("body"));
				
이런 경우도 탭을 만들지만 match=rquickExpr.exec( selector );마지막 결과는 match[1]만 획득한 것으로
  • Hello
  • 가 아니라
  • Hello
  • 이기 때문에 바디에 추가된 것은 빈 리 라벨입니다!

    좋은 웹페이지 즐겨찾기