extend文法
jQuery中的extend方法寫插件常用到的方法:
jQuery.extend([deep], target, object1, [objectN])
概述
用一個或多個其他對象來擴充一個對象,傳回被擴充的對象。
如果不指定target,則給jQuery命名空間本身進行擴充。這有助于插件作者為jQuery增加新方法。 如果第一個參數設定為true,則jQuery傳回一個深層次的副本,遞歸地複制找到的任何對象。否則的話,副本會與原對象共享結構。 未定義的屬性将不會被複制,然而從對象的原型繼承的屬性将會被複制。
參數
[deep],target,object1,[objectN]
Boolean,Object,Object,Object
注意:
deep參數隻有兩種情況:true(深複制)或者無(淺複制)。
deep參數為true的時候,若參數是兩個或者兩個以上,則是深複制。若參數是一個則是添加新函數。
沒有deep參數的時候,若參數是一個的時候,功能是添加新函數。若參數是兩個或者兩個以上的時候是淺複制。
由jQuery.extend源碼可知,deep參數預設是false,但是在調用extend的時候如果不是深複制則不能将false傳給deep,否則會将false當成target。
特别注意:
為了減少麻煩,使用jQuery.extend實作淺複制的時候,不要使用jQuery.extend(false, object1, object2, [objectN])的形式,
因為此時目标參數target不是object1,extend函數的傳回值不是object1,而是将第一個參數false轉換成對象{},并且作為目标參數,
是以extend對object1不會進行修改。jQuery.extend(false, object1, object2, [objectN])的形式等效于jQuery.extend({}, object1, object2, [objectN]),target={}。
deep:如果設為true,則遞歸合并
target:待修改對象。
object1:待合并到第一個對象的對象。
objectN:待合并到第一個對象的對象。
target,[object1],[objectN]
Object,Object,Object
注意:
這裡是淺複制
target:一個對象,如果附加的對象被傳遞給這個方法将那麼它将接收新的屬性,如果它是唯一的參數将擴充jQuery的命名空間。
object1:待合并到第一個對象的對象。
objectN:待合并到第一個對象的對象。
能實作的功能
1:将兩個或多個對象的内容合并到第一個對象
jQuery.extend( target [, object1 ] [, objectN ] )
extend方法需要至少傳入一個參數,第一個必需,後面的都是可選參數。若傳給extend是兩個或兩個以上的參數都是對象類型,那麼就會把後面所有對象的内容合并給target(第一個對象)上。
2:為jQuery添加新函數
jQuery.extend(target)
如果隻有一個參數,在這種情況下,jQuery對象本身被預設為目标對象。這樣,我們可以在jQuery的命名空間下添加新的功能。這對于插件開發者希望向 jQuery 中添加新函數時是很有用的。
jQuery源碼解釋
// 為與源碼的下标對應上,我們把第一個參數稱為`第0個參數`,依次類推
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {}, // 預設第0個參數為目标參數
i = 1, // i表示從第幾個參數凱斯想目标參數進行合并,預設從第1個參數開始向第0個參數進行合并
length = arguments.length,
deep = false; // 預設為淺度拷貝
// 判斷第0個參數的類型,若第0個參數是boolean類型,則擷取其為true還是false
// 同時将第1個參數作為目标參數,i從目前目标參數的下一個
// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
// Skip the boolean and the target
target = arguments[ i ] || {};
i++;
}
// 判斷目标參數的類型,若目标參數既不是object類型,也不是function類型,則為目标參數重新指派
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
// 若目标參數後面沒有參數了,如$.extend({_name:'wenzi'}), $.extend(true, {_name:'wenzi'})
// 則目标參數即為jQuery本身,而target表示的參數不再為目标參數
// Extend jQuery itself if only one argument is passed
if ( i === length ) {
target = this;
i--;
}
// 從第i個參數開始
for ( ; i < length; i++ ) {
// 擷取第i個參數,且該參數不為null和undefind,在js中null和undefined,如果不區分類型,是相等的,null==undefined為true,
// 是以可以用null來同時過濾掉null和undefind
// 比如$.extend(target, {}, null);中的第2個參數null是不參與合并的
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) {
// 使用for~in擷取該參數中所有的字段
// Extend the base object
for ( name in options ) {
src = target[ name ]; // 目标參數中name字段的值
copy = options[ name ]; // 目前參數中name字段的值
// 若參數中字段的值就是目标參數,停止指派,進行下一個字段的指派
// 這是為了防止無限的循環嵌套,我們把這個稱為,在下面進行比較詳細的講解
// Prevent never-ending loop
if ( target === copy ) {
continue;
}
// 若deep為true,且目前參數中name字段的值存在且為object類型或Array類型,則進行深度指派
// Recurse if we're merging plain objects or arrays
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
// 若目前參數中name字段的值為Array類型
// 判斷目标參數中name字段的值是否存在,若存在則使用原來的,否則進行初始化
if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else {
// 若原對象存在,則直接進行使用,而不是建立
clone = src && jQuery.isPlainObject(src) ? src : {};
}
// 遞歸處理,此處為2.2
// Never move original objects, clone them
target[ name ] = jQuery.extend( deep, clone, copy );
// deep為false,則表示淺度拷貝,直接進行指派
// 若copy是簡單的類型且存在值,則直接進行指派
// Don't bring in undefined values
} else if ( copy !== undefined ) {
// 若原對象存在name屬性,則直接覆寫掉;若不存在,則建立新的屬性
target[ name ] = copy;
}
}
}
}
// 傳回修改後的目标參數
// Return the modified object
return target;
};