learn
learn copied to clipboard
JavaScript专题之从零实现jQuery的extend
模拟 jQuery 的 extend
extend 的用法:合并两个或者更多的对象的内容到第一个对象中。
jQuery.extend( [deep], target, object1 [, objectN ] )
- deep,布尔值,如果为 true,进行深拷贝;false 做浅拷贝,target 就往后移动到第二个参数
- target,表示要拓展的目标,我们就称它为目标对象吧。
- 后面的参数,都传入对象,内容都会复制到目标对象中,我们就称它们为待复制对象吧。
var toString = class2type.toString;
var hasOwn = class2type.hasOwnProperty;
function isPlainObject(obj) {
var proto, Ctor;
if (!obj || toString.call(obj) !== "[object Object]") {
return false;
}
proto = Object.getPrototypeOf(obj);
if (!proto) {
return true;
}
Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
return (
typeof Ctor === "function" &&
hasOwn.toString.call(Ctor) === hasOwn.toString.call(Object)
);
}
function extend() {
// 默认不进行深拷贝
var deep = false;
var name, options, src, copy, clone, copyIsArray;
var length = arguments.length;
// 记录要复制的对象的下标
var i = 1;
// 第一个参数不传布尔值的情况下,target 默认是第一个参数
var target = arguments[0] || {};
// 如果第一个参数是布尔值,第二个参数是 target
if (typeof target == "boolean") {
deep = target;
target = arguments[i] || {};
i++;
}
// 如果target不是对象,我们是无法进行复制的,所以设为 {}
if (typeof target !== "object" && !isFunction(target)) {
target = {};
}
// 循环遍历要复制的对象们
for (; i < length; i++) {
// 获取当前对象
options = arguments[i];
// 要求不能为空 避免 extend(a,,b) 这种情况
if (options != null) {
for (name in options) {
// 目标属性值
src = target[name];
// 要复制的对象的属性值
copy = options[name];
// 解决循环引用
if (target === copy) {
continue;
}
// 要递归的对象必须是 plainObject 或者数组
if (
deep &&
copy &&
(isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))
) {
// 要复制的对象属性值类型需要与目标属性值相同
if (copyIsArray) {
copyIsArray = false;
clone = src && Array.isArray(src) ? src : [];
} else {
clone = src && isPlainObject(src) ? src : {};
}
target[name] = extend(deep, clone, copy);
} else if (copy !== undefined) {
target[name] = copy;
}
}
}
}
return target;
}