1>浅拷贝:复制引用,就是新生成的拷贝和原来的拷贝指向同一个实例对象,彼此之前操作会相互影响(就是将一个变量赋给另一个变量)
变量复制
var src = {
name:"src"
}
//复制一份src对象的应用
var target = src;
target.name = "target";
console.log(src.name);
函数复制
function shallowClone (source){
if(!source || typeof source != 'object'){//0,null,undefine,空字符串,NaN是false
throw new Error ('error');
}
var targetObj = source.constructor === Array ? [] : {};
for(var keys in source) {
if(source.hasOwnProperty(keys)){//hasOwnPrototype是让他浅复制的原因
targetObj[keys] = source[keys];
}
}
return targetObj;
}
Object.assign()
2>深拷贝:复制实例,新生成的拷贝和原来的拷贝之间没有相互影响,将对象中的数组、子对象进行深度递归遍历,直到其不是引用类型位置的时候再进行复制,这样就不会相互影响了。
1.数组
Array的slice(单层)var arr1=arr.slice(0)
concat(单层)var arr1=arr.concat()
es6的扩展运算符...只能复制单层,不可实现深层复制
var arr = [1,2,3,4,5]
var [ ...arr2 ] = arr
arr[2] = 5
console.log(arr)
console.log(arr2)
es6的Object.assign()单层复制
var arr1=Object.assign([],arr);
jq的extend
2.对象
var target = JSON.parse(JSON.stringify(source));(可以多层)可以满足基本的深复制需求,但是对于正则表达式类型、函数类型等无法进行深复制(而且会直接丢失相应的值),同时如果对象中存在循环引用的情况也无法正确处理,不支持undefine当值为undefine时他会自动跳过结果中不显示这个值
扩展运算符...只能复制单层,不可实现深层复制
var obj={
name:'shisha',
sex:'woman',
old:{
age:'20',
year:"1997"
}
}
var {...obj1}=obj;
es6的Object.assign()单层复制
var obj1=Object.assign({},obj);
jQuery中的extend
3.深复制代码
function deepCopy(p, c) {
var c = c || {};
for (var i in p) {
if (typeof p[i] === 'object') {
c[i] = (p[i].constructor === Array) ? [] : {};
deepCopy(p[i], c[i]);
} else {
c[i] = p[i];
}
}
return c;
}
var obj={a:1,b:{c:2,d:4}}
var doctor=deepCopy(obj);
var doctor1=deepCopy(obj,{e:4})
console.log(doctor);//{a:1,b:{c:2,d:4}}
console.log(doctor1);//{e:4,a:1,b:{c:2,d:4}}
4.Object.assign()单层复制
Object.assign(target, ...sources)
函数参数为一个目标对象(该对象作为最终的返回值),源对象(此处可以为任意多个)。拷贝过程中将调用源对象的getter方法,并在目标对象上使用setter方法实现目标对象的拷贝。
var obj1={a:1};
var obj2={b:2};
var obj3={c:3};
var obj=Object.assign(obj1,obj2,obj3)
console.log(obj1);//{a:1,b:2,c:3}
console.log(obj2);//{b:2}
console.log(obj3);//{c:3}
属性覆盖
var obj1=Object.assign({a:{b:2}},{a:{b:3,c:4}},{a:{b:9}})//{a:{b:9}}
实现es5版本的Object.assign
实现步骤:
1.判断是否原生支持该函数,如果不存在的话创建一个立即执行函数,该函数将创建一个assign函数绑定到Object上。
2.判断参数是否正确(目的对象不能为空,我们可以直接设置{}传递进去,但必须设置该值)
3.使用Object在原有的对象基础上返回该对象,并保存为out
4.使用for…in循环遍历出所有的可枚举的自有对象。并复制给新的目标对象(hasOwnProperty返回非原型链上的属性)
if (typeof Object.assign != 'function') {
(function () {
Object.assign = function (target) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert undefined or null to object');
}
var output = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source !== undefined && source !== null) {
for (var nextKey in source) {
if (source.hasOwnProperty(nextKey)) {
output[nextKey] = source[nextKey];
}
}
}
}
return output;
};})();}
5.jq的extend方法
1》extend(boolen,dest,src1,src2,src3...)
第一个参数boolean代表是否进行深度拷贝可以省略默认浅拷贝(true深拷贝)
函数参数为一个目标对象(该对象作为最终的返回值),源对象(此处可以为任意多个)。
后面的参数如果和前面的参数存在相同的名称,那么后面的会覆盖前面的参数值。
var obj1={a:1};
var obj2={b:2};
var obj=$.extend(obj1,obj2);
console.log(obj)//{a:1,b:2}
console.log(obj1)//{a:1,b:2}
console.log(obj2)//{b:2}
同样的问题:var obj1=$.extend({a:{b:2}},{a:{b:3,c:4}},{a:{b:9}});//{a:{b:9}}
2》省略dest将该src合并到调用extend方法的对象中去
$.extend(src)该方法就是将src合并到jquery的全局对象中去。
$.extend({
hello:function(){
alert("net")
}
})
$.hello();
$.fn.extend(src)该方法将src合并到jquery的实例对象中去
var b=$.fn.extend({
hello:function(){
alert("net")
}
})
b.hello();
xtend({
hello:function(){
alert("net")
}
})
$.hello();
$.fn.extend(src)该方法将src合并到jquery的实例对象中去
var b=$.fn.extend({
hello:function(){
alert("net")
}
})
b.hello();