jQuery의 체인 문법 실현

잊어버리지 않도록 스스로 기록을 하는 아주 오래된 화제.비교적 간단하게 썼으니 양해해 주십시오. 틀린 점이 있으면 알려 주십시오. 감사합니다.
어떻게 jQuery 대상을 생성합니까?
$(selector,context)를 직접 호출하면 됩니다. 원본이 무엇을 했는지 봅시다.
// Define a local copy of jQuery
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를 실례화합니다.fn.init 대상(그렇게 긴 이름을 보지 말고function name이라고 생각하면 된다) 그러면 이 구조 함수에서 무엇을 했을까요?
    init = jQuery.fn.init = function( selector, context ) {
		var match, elem;

		// HANDLE: $(""), $(null), $(undefined), $(false)
		if ( !selector ) {
			return this;
		}

		........

		if ( selector.selector !== undefined ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return jQuery.makeArray( selector, this );
	};

사실은 위조수 그룹의 자체 실례, 즉 jQuery를 되돌려주는 것이다.fn.init의 실례, 이것이 바로 우리가 자주 사용하는 jQuery 대상입니다.
그럼 jQuery는 어떻게 체인 문법을 실현합니까?
우리는 원본 코드를 이어서 아래를 내려다보았는데, 아래의 이 구절이 관건이다.
// Give the init function the jQuery prototype for later instantiation
init.prototype = jQuery.fn;

바로 jQuery.fn.init의 실례는 모두 jQuery를 가지고 있습니다.fn 상응하는 방법, 즉 우리가 사용하는 방법은 모두 이 위에 있다.그럼 jQuery.fn은 처음에 어떤 거예요?jQuery가 없습니다.fn도 jQuery가 없어요.fn.init.
jQuery.fn = jQuery.prototype = {
	// The current version of jQuery being used
	jquery: version,

	constructor: jQuery,

	// Start with an empty selector
	selector: "",

	// The default length of a jQuery object is 0
	length: 0,

	toArray: function() {
		return slice.call( this );
	},

	.....................
};

이것이 바로 그가 부여한 값으로 Object 대상에 해당한다.그럼 어떻게 그에게 새로운 방법을 추가합니까?그가 우리에게 무엇을 제공했는지 보시오.
jQuery.extend = jQuery.fn.extend = function() {
	var options, name, src, copy, copyIsArray, clone,
		target = arguments[0] || {},
		i = 1,
		length = arguments.length,
		deep = false;

	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;

		// skip the boolean and the target
		target = arguments[ i ] || {};
		i++;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
		target = {};
	}

	// extend jQuery itself if only one argument is passed
	if ( i === length ) {
		target = this;
		i--;
	}

	for ( ; i < length; i++ ) {
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null ) {
			// Extend the base object
			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];

				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}

				// Recurse if we're merging plain objects or arrays
				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
					if ( copyIsArray ) {
						copyIsArray = false;
						clone = src && jQuery.isArray(src) ? src : [];

					} else {
						clone = src && jQuery.isPlainObject(src) ? src : {};
					}

					// Never move original objects, clone them
					target[ name ] = jQuery.extend( deep, clone, copy );

				// Don't bring in undefined values
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}

	// Return the modified object
	return target;
};

extend를 통해 jQuery를 확장할 수 있습니다.extend는 jQuery를 확장하는 방법입니다. 이것은 제가 그를 도구처럼 이해합니다. 예를 들어 우리가 자주 사용하는 $입니다.each,$.trim 등은 모두 여기서 기원한다.그리고 jQuery.fn.extend는 우리에게 jQuery 대상을 확장하는 방법과 맞먹는다. 위아래 문장은 jQuery이다.fn.init 실례 대상 자체, 체인식 방법은 모두 여기서 기원한다.
기왕 체인식 문법이라면 그 방법이 호출된 후에 모두 무엇을 되돌려 주었을까?
분명한 것은 jQuery 대상 자체이다. 우리는removeAttr의 실현을 살펴보자.
jQuery.fn.extend({
	attr: function( name, value ) {
		return access( this, jQuery.attr, name, value, arguments.length > 1 );
	},

	removeAttr: function( name ) {
		return this.each(function() {
			jQuery.removeAttr( this, name );
		});
	}
});

 
jQuery.fn = jQuery.prototype = {
	.....................

	// Execute a callback for every element in the matched set.
	// (You can seed the arguments with an array of args, but this is
	// only used internally.)
	each: function( callback, args ) {
		return jQuery.each( this, callback, args );
	},
        .....................
}

이전 init에서prototype = jQuery.fn;this가 사실상 init의 실례임을 알 수 있다.
jQuery.extend({
               ..................................
               // args is for internal usage only
	each: function( obj, callback, args ) {
		var value,
			i = 0,
			length = obj.length,
			isArray = isArraylike( obj );

		if ( args ) {
			if ( isArray ) {
				for ( ; i < length; i++ ) {
					value = callback.apply( obj[ i ], args );

					if ( value === false ) {
						break;
					}
				}
			} else {
				for ( i in obj ) {
					value = callback.apply( obj[ i ], args );

					if ( value === false ) {
						break;
					}
				}
			}

		// A special, fast, case for the most common use of each
		} else {
			if ( isArray ) {
				for ( ; i < length; i++ ) {
					value = callback.call( obj[ i ], i, obj[ i ] );

					if ( value === false ) {
						break;
					}
				}
			} else {
				for ( i in obj ) {
					value = callback.call( obj[ i ], i, obj[ i ] );

					if ( value === false ) {
						break;
					}
				}
			}
		}

		return obj;
	},
      .....................
}

되돌아오는 결과obj를 직접 보면 그가 바로 이전에 전송한this 매개 변수, 즉 jQuery이다.fn.init의 실례 대상,removeAttr에서 마지막으로this를 호출합니다.each가 되돌아오는 대상이 바로 이 대상이다.이 대상은 jQuery를 가지고 있습니다.fn의 모든 방법입니다. 그래서 우리는 jQuery의 방법을 계속 호출할 수 있습니다.

좋은 웹페이지 즐겨찾기