深浅拷贝简介
javascript中对于Object和Array这两个类型,把一个变量赋值给另一个变量;浅拷贝只是对拷贝对象的引用,深拷贝是彻底拷贝,生成一个新的属性相同的对象
浅拷贝(shallow copy)
浅拷贝只是对拷贝对的引用,两者相互影响
浅拷贝的实现
1.简单赋值实现
例子:obj2拷贝了obj1,obj2改变,obj1也会改变,改变之后2者还是相同的
var obj1 = {a: 1}
var obj2 = obj1
obj2.b = 2
console.log(obj1) // {a: 1, b: 2}
console.log(obj2) //{a: 1, b: 2}
console.log(obj1 == obj2) // true
Object.assign()实现
例子:当第一个传参是你需要拷贝的对象(PS:Object.assign()也可以实现深拷贝)
var obj1 = {a: 1}
var obj2 = Object.assign(obj1)
obj2.b = 2
console.log(obj1) // {a: 1, b: 2}
console.log(obj2) // {a: 1, b: 2}
console.log(obj1 == obj2) // true
深拷贝(deep copy)
彻底拷贝,生成一个新的属性相同的对象
深拷贝的实现
Object.assign()实现
例子:拷贝对象不是第一个传参
var obj1 = {a: 1}
var obj2 = Object.assign({}, obj1)
obj2.b = 2
console.log(obj1) // {a: 1}
console.log(obj2) // {a: 1, b: 2}
console.log(obj1 == obj2) // false
Array.slice()可以实现数组的深拷贝(数组中不能有Object和Array,Object和Array只是浅拷贝)
var arr1 = [1, [2]]
var arr2 = arr1.slice()
arr2[1].push(3)
arr2.push(4)
console.log(arr1) // [1, [2, 3]]
console.log(arr2) // [1, [2, 3], 4]
console.log(arr1 == arr2) // false
JSON.stringify()和JSON.parse()实现
var obj1 = {a: 1}
var obj2 = JSON.parse(JSON.stringify(obj1))
console.log(obj1 == obj2) // false
obj2.b = 2
console.log(obj1) // {a: 1}
console.log(obj2) // {a: 1, b: 2}
递归实现
var deepCopy = function(obj) {
if (typeof obj !== 'object') return;
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
}
}
return newObj;
}
var obj1 = {a: 1}
var obj2 = deepCopy(obj1)
console.log(obj1 == obj2) // false
obj2.b = 2
console.log(obj1) // {a: 1}
console.log(obj2) // {a: 1, b: 2}
Object.create()实现
var deepCopy = function(obj) {
if (typeof obj !== 'object') return;
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object' ? Object.create(obj[key]) : obj[key];
}
}
return newObj;
}
var obj1 = {a: 1}
var obj2 = deepCopy(obj1)
console.log(obj1 == obj2) // false
obj2.b = 2
console.log(obj1) // {a: 1}
console.log(obj2) // {a: 1, b: 2}
jQuery.extend()实现
var obj1 = {a: 1}
var obj2 = $.extend(true, {}, obj1)
console.log(obj1 == obj2) // false
obj2.b = 2
console.log(obj1) // {a: 1}
console.log(obj2) // {a: 1, b: 2}
jQuery.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; // 默认浅拷贝
// Handle a deep copy situation
if ( typeof target === "boolean" ) { // 如果第一个参数类型为boolean,那么把该参数赋值给局部变量deep
deep = target;
target = arguments[1] || {}; // 把第二个参数赋值给target
// skip the boolean and the target
i = 2;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction(target) ) { // target不是object类型或者不是function,就赋值{}
target = {};
}
// extend jQuery itself if only one argument is passed
if ( length === i ) { // 如果只有一个参数,这时候i就是1,length也就是1,那么把target设置为调用者,也就是jQuery对象本身!同时把i递减为0
target = this; // this就是jQuery
--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 ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
if ( target === copy ) { // 防止无休止循环
continue;
}
// Recurse if we're merging plain objects or arrays
// deep是否深拷贝,copy是参数属性值
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 ) { // 浅拷贝,且属性值不为undefined
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
};
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。