제이쿼리 동작원리

윤신영·2021년 6월 23일
0

🔹 제이쿼리 동작원리

  • jQuery는 어떻게 $를 사용하는지
  • $(function() {}) 은 어떻게 기능하는가
function jQuery(a,c) {
  // Shortcut for document ready (because $(document).each() is silly)
  if ( a && a.constructor == Function && jQuery.fn.ready )
    return jQuery(document).ready(a); // (1)
 // Make sure that a selection was provided
  a = a || jQuery.context || document; // (2)
 // Watch for when a jQuery object is passed as the selector
  if ( a.jquery )
    return $( jQuery.merge( a, [] ) ); // (3)
 // Watch for when a jQuery object is passed at the context
  if ( c && c.jquery )
    return $( c ).find(a); // (4)
 // If the context is global, return a new object
  if ( window == this )
    return new jQuery(a,c); // (5)
 // Handle HTML strings
  var m = /^[^<]*(<.+>)[^>]*$/.exec(a);
  if ( m ) a = jQuery.clean( [ m[1] ] ); // (6)
 // Watch for when an array is passed in
  this.get( a.constructor == Array || a.length && !a.nodeType && a[0] != undefined && a[0].nodeType ?
  // Assume that it is an array of DOM Elements
  jQuery.merge( a, [] ) :
 // Find the matching elements and save them for later
  jQuery.find( a, c ) ); // (7)
 // See if an extra function was provided
  var fn = arguments[ arguments.length - 1 ]; // (8)
 // If so, execute it in context
  if ( fn && fn.constructor == Function ) // (9)
    this.each(fn);
}
// Map over the $ in case of overwrite
if ( typeof $ != "undefined" )
  jQuery._$ = $;
// Map the jQuery namespace to the '$' one
var $ = jQuery;

🔹 jQuery의 prototype을 정의해둔 코드

jQuery.fn = jQuery.prototype = {
  jquery: "$Rev: 509 $",
  ...,
  get: function( num ) {
    // Watch for when an array (of elements) is passed in
    if ( num && num.constructor == Array ) {
      // Use a tricky hack to make the jQuery object
      // look and feel like an array
      this.length = 0;
      [].push.apply( this, num );
      return this;
    } else
    return num == undefined ?
      // Return a 'clean' array
      jQuery.map( this, function(a){ return a } ) :
      // Return just the object
      this[num];
  },
  ...,
  find: function(t) {
    return this.pushStack( jQuery.map( this, function(a){
      return jQuery.find(t,a);
    }), arguments );
  },
  ...,
  pushStack: function(a,args) {
    var fn = args && args[args.length-1];
    if ( !fn || fn.constructor != Function ) {
      if ( !this.stack ) this.stack = [];
      this.stack.push( this.get() );
      this.get( a );
    } else {
      var old = this.get();
      this.get( a );
      if ( fn.constructor == Function )
        return this.each( fn );
      this.get( old );
    }
    return this;
  }
}

🔹 jQuery.extend라고 숨겨진 코드

jQuery.extend = jQuery.fn.extend = function(obj,prop) {
  if ( !prop ) { prop = obj; obj = this; }
  for ( var i in prop ) obj[i] = prop[i];
  return obj;
};

jQuery.extend({
  ...
  find: function( t, context ) {
    // Make sure that the context is a DOM Element
    if ( context && context.nodeType == undefined ) // (1)
      context = null;
    // Set the correct context (if none is provided)
    context = context || jQuery.context || document; // (2)
    if ( t.constructor != String ) return [t]; // (3)
    if ( !t.indexOf("//") ) { // (4)
      context = context.documentElement;
      t = t.substr(2,t.length);
    } else if ( !t.indexOf("/") ) {
      context = context.documentElement;
      t = t.substr(1,t.length);
      // FIX Assume the root element is right :(
      if ( t.indexOf("/") >= 1 )
        t = t.substr(t.indexOf("/"),t.length);
      }
    }
    var ret = [context];
    var done = [];
    var last = null;
    while ( t.length > 0 && last != t ) { // (5)
      var r = [];
      last = t;
      t = jQuery.trim(t).replace( /^\/\//i, "" ); // (6)
      var foundToken = false;
      for ( var i = 0; i < jQuery.token.length; i += 2 ) { // (7)
        if ( foundToken ) continue;
        var re = new RegExp("^(" + jQuery.token[i] + ")");
        var m = re.exec(t);
        if ( m ) {
          r = ret = jQuery.map( ret, jQuery.token[i+1] );
          t = jQuery.trim( t.replace( re, "" ) );
          foundToken = true;
        }
      }
      if ( !foundToken ) { // (8)
        if ( !t.indexOf(",") || !t.indexOf("|") ) { // (9)
          if ( ret[0] == context ) ret.shift();
          done = jQuery.merge( done, ret );
          r = ret = [context];
          t = " " + t.substr(1,t.length);
        } else { // (10)
          var re2 = /^([#.]?)([a-z0-9\\*_-]*)/i;
          var m = re2.exec(t); // (11)
          if ( m[1] == "#" ) { // (12)
            // Ummm, should make this work in all XML docs
            var oid = document.getElementById(m[2]); // (13)
            r = ret = oid ? [oid] : [];
            t = t.replace( re2, "" );
          } else {
            if ( !m[2] || m[1] == "." ) m[2] = "*";
            for ( var i = 0; i < ret.length; i++ )
              r = jQuery.merge( r,
                m[2] == "*" ?
                  jQuery.getAll(ret[i]) :
                  ret[i].getElementsByTagName(m[2])
                );
            }
          }
        }
        if ( t ) { // (14)
          var val = jQuery.filter(t,r);
          ret = r = val.r;
          t = jQuery.trim(val.t);
       }
     }
     if ( ret && ret[0] == context ) ret.shift(); // (15)
     done = jQuery.merge( done, ret ); // (16)
     return done;
   },
profile
개발자

0개의 댓글