jQuery 利用extend进行扩展。
参考jQuery API关于extend 的用法:
$.extend([deep],target,object1,objectN)
$.fn.extend(object)
extend函数结构分析:
jQuery.extend = jQuery.fn.extend = function() {
变量的声明
if(){} //是否是深拷贝
if(){} //参数是否正确
if(){} //是否是插件的情况
for() { //多个对象情况
if() //防止循环引用
if() //深拷贝
else if //浅拷贝
}
}
extend函数逐行分析:
if 第一个参数是boolean值,deep将保持传递进来的boolean值,target 变为第二个参数,i变为2
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
... }}
if 赋值完后的target不是对象也不是函数,则 target赋值为一个空{};
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
if () {}
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
...
}
}
if 实参的长度等于i ( 意义等同于 当第一个参数不是boolean时,i=1,即实参的长度为1,只传入一个参数;否则i=2 ,即实参的长度为2,传入2个参数)也就是说,没有传入目标对象时,target赋值为this;i的长度-1;
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
...
if ( length === i ) {
target = this;
--i;
}
...
}
开始for循环
如果除boolean值外,传入了target参数(实参个数大于等于3),则从target参数之后的参数开始循环;
如果除boolean值外,没有传入了target参数(实参个数小于等于2),则从boolean值之后开始循环(没有boolean参数,则从第一个参数开始循环)。
for in 内的第一个if防止了循环引用,循环引用实例:
var a={n:1};
var b={0:a};
a[n]=b[0]; //发生循环引用,会无限制循环
接下来的if ...else...区分 深拷贝和浅拷贝
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
...
for ( ; i < length; i++ ) {
if ( (options = arguments[ i ]) != null ) {
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
if ( target === copy ) {
continue;
}
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else {
//src 是对象则赋值给clone,否则 clone赋值为空{}
clone = src && jQuery.isPlainObject(src) ? src : {};
}
target[ name ] = jQuery.extend( deep, clone, copy ); //递归实现深拷贝
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
return target;
}