2013-01-30
JQuery框架跟踪笔记(2)--大体结构和extend
上次根据ID跟踪,我们了解了JQuery的包装过程,同时也暴露了JQuery的大体结构....
本次将不把主要精力放在选择器上,而是JQuery的大体框架结构和extend扩展函数...
每天写点,想想,差不多开学的时候,就把整个JQuery的大体源码弄清楚了吧...

补充资料:
1.
Jquery1.2.6中文注释源码(只有部分是中文)

这里的所说的结构,只和(1)和extend相关...其他的我都隐藏了...
Code:js

(function () {
    //构造函数
    var jQuery = window.jQuery = window.$ = function (selector, context) {
        return new jQuery.fn.init(selector, context);
    };
    //
    //挂载静态函数
    jQuery.fn = jQuery.prototype = {
       
          init: function (selector, context){},
        //jquery: "1.2.6",
        //size: function (){},
        //......

    };
    //为jQuery.fn.init挂载全局静态函数
    jQuery.fn.init.prototype = jQuery.fn;
    //扩展代理
    jQuery.extend = jQuery.fn.extend = function () { };

    //向jQuery扩展函数
    jQuery.extend({

    });
    //...
    //...
    //...
    //向 jQuery.fn扩展函数
    jQuery.fn.extend({

    });
    //....
    //...
    //...
})();


上面是本次调试跟踪的大体框架,基本上包含了整个JQuery结构(上面的注释我可能写得不太准确,仅作参考)...
首先我们可以由构造函数看到,JQUERY的对象最终是由jQuery.fn.init包装的....
最直接的证明   jQuery.fn.init.prototype = jQuery.fn;这句话...
所以在之前我们可以看到 jQuery.fn = jQuery.prototype = {}这里第一次挂载了部分静态函数,在  jQuery.fn.init.prototype = jQuery.fn;这里,我们又把这些函数挂载到了jQuery.fn.init.....
所以最终的对象是jQuery.fn.init.....
这里可以看到由new JQuery()的对象是没有意义的,因为JQ的大部分操作是针对DOM的,而 jQuery.prototype所挂载的只是部分和全局静态函数....

extend()

JQ给开发者扩展功能,这是开发JQ插件的一个常用函数,可以把自定义OBJECT,function等挂载到全局和实例对象....
那么现在我来跟踪这个函数,测试代码如下
Code:js
//test A
         alert($("#A").html());
         $.extend({
            test: function () { alert('hello!!'); }
        });
         $.test();//消息hello!!
         $("#A").test();//报错,无此方法


Code:js
//test B
         alert($("#A").html());
         $.fn.extend({
            test: function () { alert('hello!!'); }
        });
         $.test();//报错,无此方法
         $("#A").test();//消息hello!!

根据前面给的结构 jQuery.extend = jQuery.fn.extend = function () { };这里可以看出来....
jQuery.extend是JQUERY全局静态扩展,而 jQuery.fn.是实例对象扩展,
何以证明?
jQuery.fn.init.prototype = jQuery.fn;
jQuery.extend = jQuery.fn.extend = function () { };
从这里可以看到,jQuery.fn.init的原型对象是jQuery.fn;,那么对jQuery.fn;的任何扩展也就是对jQuery.fn.init的扩展...
而jQuery.fn.init是我们得到的包装后的JQ对象

下面给出jQuery.extend = jQuery.fn.extend = function () { };源码:
Code:js

	///	<summary>
    ///		用一个或多个其他对象来扩展一个对象,返回被扩展的对象。
    ///		用于简化继承。
	///		jQuery.extend(settings, options);
	///		var settings = jQuery.extend({}, defaults, options);
	///		Part of JavaScript
	///	</summary>
	///	<param name="target" type="Object">
    ///		 待修改对象。
	///	</param>
	///	<param name="prop1" type="Object">
    ///		 待合并到第一个对象的对象。
	///	</param>
	///	<param name="propN" type="Object" optional="true" parameterArray="true">
    ///		 (可选) 待合并到第一个对象的对象。
	///	</param>
	///	<returns type="Object" />

	// copy reference to target object
	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;

	// Handle a deep copy situation
	if ( target.constructor == Boolean ) {
		deep = target;
		target = arguments[1] || {};
		// skip the boolean and the target
		i = 2;
	}

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

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

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

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

				// Recurse if we're merging object values
				if ( deep && copy && typeof copy == "object" && !copy.nodeType )
					target[ name ] = jQuery.extend( deep, 
						// Never move original objects, clone them
						src || ( copy.length != null ? [ ] : { } )
					, copy );

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

			}

	// Return the modified object
	return target;



这里我就简写了,不贴图,你们可以自己调试哈,源码已经贴出来了
首先通过一系列的检查,把this赋给target,这个this是你调用的对象,在这里只有JQuery和JQuery.fn....

Code:js

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

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

				// Recurse if we're merging object values
				if ( deep && copy && typeof copy == "object" && !copy.nodeType )
					target[ name ] = jQuery.extend( deep, 
						// Never move original objects, clone them
						src || ( copy.length != null ? [ ] : { } )
					, copy );

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

			}


然后options 指向传过去的对象arguments[ i ],再通过for..in把options的属性和方法名,分别在target下建立索引(JS中 A[b]等效于A.b)...
和把这个属性复制给copy,然后做其他处理,最后再把刚刚建立的索引指向copy...
最后就把传过去的对象挂载到了JQuery或者JQury.fn上.....






BreezeDust    发表于  19:57:04    Tag: 技术应用
更多
姓名
Copyright (C) 2011-now  BreezeDust(Yang Li), All Rights Reserved  E-mail:BreezeDust@qq.com