jQuery剝皮二 - extend

jquery1.4  jquery1.4下載jquery

這裏使用了 jQuery1.4,爲何使用 1.4 由於 1.4 不少特性沒有添加分析起來相對容易。api


extend 能夠說是 jQuery 用的最多的函數之一了,除了核心的幾個函數以外其餘的幾乎所有用 extend 進行原型或者靜態函數的擴展。下面來看看 extend 若是完成這樣的工做的吧數組

jQuery.extend = jQuery.fn.extend = function() {
	// copy reference to target object
	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;

	// Handle a deep copy situation
    // 深度拷貝
	if ( typeof target === "boolean" ) {
		deep = target;                            // 修正深度拷貝
		target = arguments[1] || {};              // 修正目標
		// skip the boolean and the target        // 若是是深度拷貝 修正循環(跳過第一個參數(0)和目標(1))
		i = 2;
	}

	// Handle case when target is a string or something (possible in deep copy)
    // 確保目標元素是對象且不是函數,但能夠是函數對象(new 函數)
	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
		target = {};
	}

	// extend jQuery itself if only one argument is passed
    // 當擴展的對象只有一個的時候,就視爲擴展 jQuery
	if ( length === i ) {
		target = this;            // 修正 this 爲jQuery
		--i;
	}
    // 遍歷參數
	for ( ; i < length; i++ ) {
		// Only deal with non-null/undefined values
        // 遍歷不是 null 的值(對象)
		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 object literal values or arrays
                // 深拷貝,且 copy 是對象或者數組
                /**
                * deep => true
                * copy == true
                * copy => 必須是絕對對象 或 copy 是一個數組
                * 
                */
				if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) {
                    /**
                    * 若是目標元素和要拷貝的元素有相同的 key 而且也是對象或者數組那麼就返回目標對象的 key
                    * 不然建立一個對應的類型用於保存數據
                    */
					var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src
						: jQuery.isArray(copy) ? [] : {};

					// 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 的一些用法 手冊描述函數

一、這種是最基本的用法oop

var t = $.extend({a:"123"}, {b:'456'});
console.log(t);
//Object {a: "123", b: "456"}

二、深度拷貝this

var o1 = {
    txt: "123",
    a: {
        'a_text': 'a_text'
    }
};
var o2 = {
    txt1: '456',
    b: {
        'b_text': '123'
    }
};
debugger;
var t = $.extend(false,o1,o2);

t['b']['b_text'] = '改變成文本';
console.log(t);
console.log(o1,o2);

// -----------------------------深度克隆------------------------------------
var o1 = {
   txt: "123",
    a: {
        'a_text': 'a_text'
    }
};
var o2 = {
    txt1: '456',
    b: {
        'b_text': '123'
    }
};
debugger;
var t = $.extend(true,o1,o2);

t['b']['b_text'] = '改變成文本';
console.log(t);
console.log(o1,o2);

咱們看當深度克隆參數爲 false 的時候,擴展出來的對象 key 爲 b 的和元素對象 key 爲 b 的是指向的同一個引用。因此當我改變了克隆回來的對象 t 值 'b_text' 的時候原始對象也跟着變了。spa

再來看看深度克隆的狀況,當我改變了克隆回來的對象 t 值 'b_text' 的時候原始對象沒有跟着變了。.net


三、接下來看看爲 jQuery 擴展插件的狀況插件

jQuery.extend = jQuery.fn.extend = function(){};

他這裏爲 jQuery 靜態函數 和 原型都添加了 extend 函數, 因此咱們要編寫插件只須要給原型添加一個擴展函數就能夠啦。debug

$.fn.extend({tudou:function(){alert('hello tudou')}});

看一下他這裏怎麼實現的,其實原理很簡單。

// 當擴展的對象只有一個的時候,就視爲擴展 jQuery
if ( length === i ) {
	target = this;            // 修正 this 爲jQuery
	--i;
}

當你只傳遞一個對象的時候他會把 擴展的目標指向當前 this,因此能很方便的進行插件編寫。

好啦結束了。。。

相關文章
相關標籤/搜索