jquery之深拷贝

jquery3.4.0源码解析

####1. jquery之深拷贝

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
// 初始化目标值为参数列表第一项,如果没有是假值则为{}
target = arguments[ 0 ] || {},
// 下标为1;
i = 1,
// 参数列表长度
length = arguments.length,
// 默认不深拷贝
deep = false;

// 处理深度复制情况
// 如果第一项是布尔值
if ( typeof target === "boolean" ) {
// 把参数第一项赋值给deep变量,让用户自定义是否深度拷贝
deep = target;

// 跳过布尔值和目标值
// 此时目标值为参数列表第二项
target = arguments[ i ] || {};
// 此时下标为2
i++;
}

// 当目标是字符串或其他内容时处理大小写(可能是深拷贝)
// 当目标值不是对象或者不是一个函数时(这个时候目标值可能是参数列表第一项或者第二项,即用户第一项传的布尔值时),重新为目标值赋值{}
if ( typeof target !== "object" && !isFunction( target ) ) {
target = {};
}

// 如果只传递了一个参数,则扩展jquery本身
// 可能是$.extend({}或者$.extend([true/false], {})
if ( i === length ) {
target = this;
i--; // 0 或者 1
}

// 这里是jquery深/浅拷贝方法的主要逻辑
for ( ; i < length; i++ ) {

// 只处理非空/未定义的值
if ( ( options = arguments[ i ] ) != null ) {

// 扩展基础对象
for ( name in options ) {
copy = options[ name ];

// 防止对象.原型污染
// 防止永不结束的循环
if ( name === "__proto__" || target === copy ) {
continue;
}

// 如果要合并纯对象或数组,则递归
if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
( copyIsArray = Array.isArray( copy ) ) ) ) {
src = target[ name ];

// 确保源值的类型正确
if ( copyIsArray && !Array.isArray( src ) ) {
clone = [];
} else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
clone = {};
} else {
clone = src;
}
copyIsArray = false;

// 从不移动原始对象,克隆它们
target[ name ] = jQuery.extend( deep, clone, copy );

// 不要引入未定义的值
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}

// 返回修改后的对象
return target;
};