1. jQuery 的深复制
function copy() {
var options, // 被复制对象,主要是用于遍历其属性
name, // 属性名
src, // 复制到的对象
copy, // 被复制对象的属性
copyIsArray, // 被复制对象的该属性是一个数组类型
clone, // 克隆到的临时对象
target = arguments[ 0 ] || {}, // target是第一个参数或者空对象
i = 1, // 指向对象
length = arguments.length, // 参数数量
deep = false; //
// Handle a deep copy situation
if ( typeof target === "boolean" ) { // 第一个参数是boolean类型
deep = target; // 是否深度复制
// Skip the boolean and the target
target = arguments[ i ] || {}; // 此时i = 1,如果有第二个参数,target是第二个参数,否则为空对象
i++; // i = 2
}
// target指向需要拷贝到的对象,i指向需要被拷贝的第一个对象
// Handle case= when target is a string or something (possible in deep copy)
// target 是string或者其他(可能是深拷贝的对象)
// target 不是object类型也不是function类型
// 即target不是引用类型,target是一个值类型
// 那么target是一个空对象
if ( typeof target !== "object" && !isFunction( target ) ) {
target = {};
}
// Extend jQuery itself if only one argument is passed
// 如果只有一个参数那么,默认是jQuery被拓展的对象
// 此时,i = 2,或者 i = 1
// target 指向需要拷贝到的对象
// i 指向下一个需要拷贝到的对象的下一个参数
// $.extend(boolean, obj1 [,obj2])
// i === length 说明已无后续参数,所以结果就是this
// target指向需要拷贝到的对象,i指向第一个需要被拷贝的对象
// 如果 i === length 这说明 i 指向的位置不存在
// 那么此时只有两个参数,boolean,target
// 或者只有一个参数target
// 那么就将该参数复制到对象上
if ( i === length ) {
target = this;
i--;
// i 指向需要被拷贝的对象
}
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
// 仅处理非空/尚未赋值的对象
if ( ( options = arguments[ i ] ) != null ) {
// Extend the base object
// 拓展基本对象
for ( name in options ) {
// 对于options的每一个属性,name是属性名
copy = options[ name ];
// Prevent Object.prototype pollution
// 阻止Object.prototype污染
// Prevent never-ending loop
// 阻止永不结束的循环,只能检测一层嵌套
if ( name === "__proto__" || target === copy ) {
continue;
}
// Recurse if we're merging plain objects or arrays
// 如果是纯粹的对象或者数组则需要合并
// copy 不为空
// deep 深拷贝
// 是纯粹的object或者是数组
if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
( copyIsArray = Array.isArray( copy ) ) ) ) {
src = target[ name ];
// Ensure proper type for the source value
// copyIsArray:copy对象中的这一项是数组
// src:target对象中的这一项不是数组
// 那么让clone是一个数组
if ( copyIsArray && !Array.isArray( src ) ) {
clone = [];
} else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
// copy对象中的这一项不是是数组
// src中的这一项不是纯粹的对象
clone = {};
} else {
clone = src;
}
copyIsArray = false;
// 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
// 返回修改后的对象
return target;
};
$.extend( [deep ], target, object1 [, objectN ] )
(来自:菜鸟教程)
是否深复制、目标对象、被复制的对象
2. 仿写一个自己的
jQuery的extend
方法,支持多个对象,这里实现一个简单的。
function myCopy() {
var target, // 结果
copy, // 属性值
source = arguments[0]; // 需要复制的对象
if (!source) {
return source;
}
if ( ( typeof source === "object" ) ) {
target = new A.constructor(); // 保证结果的 原型和构造函数 与原对象一致
for ( name in source) {
if (!A.hasOwnProperty(name)) { // 属性不在原型上,说明在原型链上,那就跳过
continue;
}
copy = source[name]; // copy:需要拷贝的属性的值,name:需要拷贝的属性的属性名
target[ name ] = myCopy( copy );// 复制copy
}
}
else {
// 包括值类型和函数
target = source;
}
return target;
}