/*extend()插件扩展*/
jQuery.extend = jQuery.fn.extend = function() {
var src, copyIsArray, copy, name, options, clone,
target = arguments[0] || {}, //获取第一个参数赋值给target
i = 1,
length = arguments.length,
deep = false;
//第一个参数为布尔值时同时也是为true时: 执行这步时 i=2
if (typeof target === "boolean") {
deep = target; //将布尔值的结果 赋值给 deep变量
target = arguments[1] || {}; //在将第二个参数重新赋值给target变量
i = 2;
}
//如果第一个参数不是布尔值,继续往下看
//如果第一个参数不是object类型并且也不是function类型时: 执行这步时 i=1
if (typeof target !== "object" && !jQuery.isFunction(target)) { //执行以下代码
target = {}; //那么就将点一个参数设置为空对象
}
//如果只有一个参数时,并且是对象或者函数类型: 执行这步时 i=0
if (length === i) { //判断接受参数的数量
target = this; //把jQuery对象赋值给target
--i;
}
// 可以传入多个复制源
// i 是从 1或2
// 传入布尔值时(一般为true,不传时默认已经是false了) 还定义了目标对象 i=2
for (; i < length; i++) {
// Only deal with non-null/undefined values
// 将每个源的属性全部复制到 target 上
if ((options = arguments[i]) != null) {
// Extend the base object
for (name in options) {
// src 是源(即本身)的值
// copy 是即将要复制过去的值
src = target[name];
copy = options[name];
// Prevent never-ending loop
// 防止有环,例如 extend(true, target, {'target':target});
if (target === copy) {
continue;
}
// Recurse if we're merging plain objects or arrays
// 这里是递归调用,最终都会到下面的 else if 分支
// jQuery.isPlainObject 用于测试是否为纯粹的对象
// 纯粹的对象指的是 通过 "{}" 或者 "new Object" 创建的
// 如果是深复制
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
// 返回新的 target
// 如果 i < length ,是直接返回没经过处理的 target,也就是 arguments[0]
// 也就是如果不传需要覆盖的源,调用 $.extend 其实是增加 jQuery 的静态方法
return target;
}; //13
extend