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; }