依Jquery的1.3.2版來看, 內部設定時
函數(extend)被使用了18次, 關鍵字 .extend(

所以這篇文章就要來研究一下這函數在做什麼

extend的定義:Jquery對外開放的函數, 用來擴充及複寫原有函數內容, 或者合併二個物件內容。

一般在事先定義類別函數可以使用以下宣告語法

function obj_base(){	
	this.extend = function(obj){};
}

而物件被產生後, 要修改函數內容, 可以使用以下語法

var ob = new obj_base();
ob.extend = function(obj){};

或者以下語法也可以達到相同目的,
而Jquery的extend函數也是使用這個的方式來達到擴充及複寫

var ob = new obj_base();
ob['extend'] = function(obj){};

使用簡單的程式碼來表達,如下

/*產生物件*/
var ob = new obj_base();
/*擴充函數*/
ob.extend({
	A:function(){alert('IS_A');}
	B:function(){alert('IS_B');}
	C:function(){alert('IS_C');}
});
/*執行擴充函數*/
ob.B();

/*類別內容*/
function obj_base(){
	var me = this;
	this.extend = function(obj){
		for(var key in obj){
			me[key]=obj[key];
		}
	}
}

回頭來看jQuery.extend內容

jQuery.extend = jQuery.fn.extend = function() {
	// copy reference to target object
	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;	
	// Handle a deep copy situation
	if ( typeof target === "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" && !jQuery.isFunction(target) )
		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;
};

它提供了三種的參數內容
jQuery.extend({key:value}):擴充及修改jQuery本身的函數, 在jQuery檔內很常見。

jQuery.extend({
	is_new_fn:function(){
		alert('use new function');
	}
});

jQuery.extend(obj, {key:value}):擴充及修改傳入物件的函數, 在修改插件時會比較常用。
以jQuery ui datepicker為例, 可以透過以下方式修改星期顯示的數值

jQuery.extend(jQuery.datepicker._defaults,{	
	dayNames: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
	dayNamesShort: ['日', '一', '二', '三', '四', '五', '六'],
	dayNamesMin: ['日', '一', '二', '三', '四', '五', '六']
});

以上二個參數方式, 主要功能為擴充及修改

而造成jQuery.extend函數複雜的原兇是以下參數例子

jQuery.extend(bool, obj, obj1, obj2...,objN):執行結果是將obj1, obj2...,objN全部的內容複製到obj上, 而bool是在決定是否遞迴。

透過以下範例來說明, 建立A, B 二個物件, 讓 C 透過 extend 來取得 A, B 物件內容, 而 D 直接等於 A, 在執行過程中去修改 A.ax 內容。
最後輸出結果來看, A物件的修改會影響D物件, 而C物件卻是獨立個體, 同時還包含了B物件的方法。

	var A = {
		ax:function(n){return n+'is_a_fn';}
	};
	
	var B = {
		bx:function(n){return (n+'is_b_fn');}
	};
	
	var C = extend(true, {}, A, B);
	var D = A;
	var S ='';
	S += '\n'+A.ax('A:');
	S += '\n'+C.ax('C:');
	S += '\n'+D.ax('D:');
	
	A.ax = function(n){return (n+'is_new_a_fn');}
	S += '\n\n修改A.ax後';
	S += '\n'+A.ax('A:');
	S += '\n'+C.ax('C:');
	S += '\n'+D.ax('D:');
	
	S += '\n\nC物件具有B物件的方法';
	S += '\n'+C.bx('C:');
	
	alert(S);
	
function extend() {
	
	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
	deep = target;
	target = arguments[1] || {};
	i = 2;
	for ( ; i < length; i++ )		
		if ( (options = arguments[ i ]) != null )			
			for ( var name in options ) {
				var src = target[ name ], copy = options[ name ];
				if ( target === copy )
					continue;
				if ( copy !== undefined )
					target[ name ] = copy;
			}
	
	return target;
	
};

jQuery檔內有一段code如下, 透過上面的說明, 應該就可以理解它到底做了什麼好事。

s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));


以上~~希望對您有所幫助^^

arrow
arrow
    全站熱搜

    aqr199xx 發表在 痞客邦 留言(0) 人氣()