jQuery.extend()
用于将一个或多个对象 合并到目标对象中
- 参数:
- deep 值类型:boolean 是否深度遍历; 缺省值 :false;
- target 值类型:Object 目标对象(被扩展的对象);
- Object1…ObjectN 值类型:Obejct 扩展的对象;
- 实现:
1. 声明全局变量;
- i 变量存储 扩展对象在参数中的开始位置;默认为1 即arguments[1]
- target 默认 arguments[0] 不存在则创建一个{}
- length 传入参数的个数,用于下面循环赋值时用;
/*
*target被扩展的对象
*length参数的数量
*deep是否深度操作
*/
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
2. 判断传入的参数值
- target 是否为boolean类型 ;是 :改变deep 默认值,i 顺延一位 为2
- 判断target 值 是否合法;
- 判断length 长度 如果 没有传入扩展对象则把this 赋值给target **?? 不是很懂**
// target为第一个参数,如果第一个参数是Boolean类型的值,则把target赋值给deep
// deep表示是否进行深层面的复制,当为true时,进行深度复制,否则只进行第一层扩展
// 然后把第二个参数赋值给target
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// 将i赋值为2,跳过前两个参数
i = 2;
}
// target既不是对象也不是函数则把target设置为空对象。
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
// 如果只有一个参数,则把jQuery对象赋值给target,即扩展到jQuery对象上
if ( length === i ) {
target = this;
// i减1,指向被扩展对象
--i;
}
3. 判断传入的参数值
- 循环遍历 arguments[i] 的属性,存到 copy 变量中;target 原有的属性存储到 src 中;
- 判断 这个copy 是否是一个纯粹的对象通过($.isPlainObject()方法) 或者 是一个数组,且 deep 参数传入值为true;
- 如果满足递归条件 再次调用 $.extend(); 传入 src 作为target copy 作为扩展对象;
- 如果不满足条件 直接 赋值;
- 完成循环 返回 对象;
// 开始遍历需要被扩展到target上的参数
for ( ; i < length; i++ ) {
// 处理第i个被扩展的对象,即除去deep和target之外的对象
if ( (options = arguments[ i ]) != null ) {
// 遍历第i个对象的所有可遍历的属性
for ( name in options ) {
// 根据被扩展对象的键获得目标对象相应值,并赋值给src
src = target[ name ];
// 得到被扩展对象的值
copy = options[ name ];
// 这里为什么是比较target和copy?
if ( target === copy ) {
continue;
}
// 当用户想要深度操作时,递归合并
// copy是纯对象或者是数组
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
// 如果是数组
if ( copyIsArray ) {
// 将copyIsArray重新设置为false,为下次遍历做准备。
copyIsArray = false;
// 判断被扩展的对象中src是不是数组
clone = src && jQuery.isArray(src) ? src : [];
} else {
// 判断被扩展的对象中src是不是纯对象
clone = src && jQuery.isPlainObject(src) ? src : {};
}
// 递归调用extend方法,继续进行深度遍历
target[ name ] = jQuery.extend( deep, clone, copy );
// 如果不需要深度复制,则直接把copy(第i个被扩展对象中被遍历的那个键的值)
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
// 原对象被改变,因此如果不想改变原对象,target可传入{}
return target;
};