深拷贝
var a = {name:1, sya:function(){ console.log("打印")},age:undefined}; // {name:1,sya:f}
var b = JSON.parse(JSON.stringify(a)); // {name:1}
function Obj() {
this.func = function () {
alert(1)
};
this.obj = {
a: 1
};
this.arr = [1, 2, 3];
this.und = undefined;
this.reg = /123/;
this.date = new Date(0);
this.NaN = NaN;
this.infinity = Infinity;
this.sym = Symbol(1);
}
let obj1 = new Obj();
Object.defineProperty(obj1, 'innumerable', {
enumerable: false,
value: 'innumerable'
});
console.log('obj1', obj1);
let str = JSON.stringify(obj1);
let obj2 = JSON.parse(str);
console.log('obj2', obj2);
// 深拷贝
var sourceObj = {
name: 'tt',
age: 18,
job: 'web',
friends: ['t1', 't2']
}
// util作为判断变量具体类型的辅助模块
var util = (function() {
var class2Type = {}
var objTypes = ["Null","Undefined","Number","Boolean","String","Object","Function","Array","RegExp","Date”]
objTypes.forEach(function(item) {
class2Type['[object ' + item + ']'] = item.toLowerCase()
})
function isType(obj, type) {
return getType(obj) === type
}
function getType(obj) {
return class2type[Object.prototype.toString.call(obj)] || 'object'
}
return {
isType: isType,
getType: getType
}
})()
// deep参数用来判断是否是深度复制
function copy(obj, deep){
// 如果obj不是对象,那么直接返回值就可以了
if(obj == null || typeof obj !== 'object'){
return obj
}
// 定义需要的局部变量,根据obj的类型来调整target的类型
var i,
target = util.isType(obj,"array") ? [] : {},
value,
valueType
for(i in obj){
value = obj[i]
valueType = util.getType(value)
// 只有在明确执行深复制,并且当前的value是数组或对象的情况下才执行递归复制
if(deep && (valueType === "array" || valueType === "object")){
target[i] = copy(value)
}else{
target[i] = value
}
}
return target
}
var targetObj = copy(sourceObj, true);
targetObj.friends.push ('t3');
console.log(sourceObj) // ['t1', 't2']
// 深拷贝
Object.prototype.clone = function() {
var Constructor = this.constructor
var obj = new Constructor()
for (var attr in this) {
if (this.hasOwnProperty(attr)) {
if (typeof this[attr] !== 'function') {
if (this[attr] === null) {
obj[attr] = null
} else {
obj[attr] = this[attr].clone()
}
}
}
}
return obj
}
/* Method of Array*/
Array.prototype.clone = function() {
var thisArr = this.valueOf()
var newArr = []
for (var i = 0; i < thisArr.length; i++) {
newArr.push(thisArr[i].clone())
}
return newArr
}
/* Method of Boolean, Number, String*/
Boolean.prototype.clone = function() {
return this.valueOf()
}
Number.prototype.clone = function() {
return this.valueOf()
}
String.prototype.clone = function() {
return this.valueOf()
}
/* Method of Date*/
Date.prototype.clone = function() {
return new Date(this.valueOf())
}
/* Method of RegExp*/
RegExp.prototype.clone = function() {
var pattern = this.valueOf()
var flags = ''
flags += pattern.global ? 'g' : ''
flags += pattern.ignoreCase ? 'i' : ''
flags += pattern.multiline ? 'm' : ''
return new RegExp(pattern.source, flags)
}
function deepClone(source){
// 判断复制的目标是数组还是对象
const targetObj = source.constructor === Array ? [] : {};
for(let keys in source){ // 遍历目标
if(source.hasOwnProperty(keys)){
if(source[keys] && typeof source[keys] === 'object'){
targetObj[keys] = source[keys].constructor === Array ? [] : {};
targetObj[keys] = deepClone(source[keys]);
}else{ // 如果不是,就直接赋值
targetObj[keys] = source[keys];
}
}
}
return targetObj;
}
//测试一下
var a = {name:1, sya:function(){ console.log("打印")},age:undefined};
var b = deepClone(a);
b.name=2;
console.log(a)//{name:1,sya:f,age:undefined}
console.log(b)//{name:2,sya:f,age:undefined}
// 深拷贝函数并不能复制不可枚举的属性以及 Symbol 类型;
// 这种方法只是针对普通的引用类型的值做递归复制,而对于 Array、Date、RegExp、Error、Function 这样的引用类型并不能正确地拷贝;
// 对象的属性里面成环,即循环引用没有解决。