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
//如果第一个参数是boolean类型
//修正参数,将第二个参数作为target
if
(
typeof
target ===
"boolean"
) {
deep = target;
// skip the boolean and the target
target = arguments[ i ] || {};
//i++是为了后续 i === length的判断
i++;
}
// Handle case when target is a string or something (possible in deep copy)
//如果目标既不是对象也不是方法(例如给基本类型扩展属性方法和属性不会报错但是是无用的),修正target为 js对象
if
(
typeof
target !==
"object"
&& !jQuery.isFunction(target) ) {
target = {};
}
// extend jQuery itself if only one argument is passed
//如果只有一个参数,修正对象为JQuery函数或JQuery对象
if
( i === length ) {
target =
this
;
//修正target所在位置,后面的都是要添加给target的对象
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
//如果target和copy是同一个对象,略过,防止自己的属性引用了本身对象导致的循环引用,以致GC无法回收
if
( target === copy ) {
continue
;
}
// Recurse if we're merging plain objects or arrays
//如果是deep为true,并且要添加给target的copy为对象获数组
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;
};