思路

首先是用Object.prototype.toString.call(obj)来得到传入的值的类型,如果是几个基本类型,则直接返回值就可以了

如果是引用类型,则通过深拷贝函数递归进行再次拷贝。

注:也可以用constructor判断类型(参见deepClone2函数)

代码

/**
* 实现深拷贝
* @param {*} obj
* @returns {*} 拷贝完的对象
*/
function deepCopy(obj) {
let type = Object.prototype.toString.call(obj);
type = type.split(' ')[1].split(']')[0];
console.log(type);
if (type === 'Number') {
return obj;
} else if (type === 'Object') {
const new_obj = {};
for (item in obj) {
if (typeof item === 'object') {
new_obj[item] = deepCopy(item);
} else {
new_obj[item] = obj[item];
}
}
return new_obj;
} else if (type === 'Function') {
return obj;
} else if (type === 'String') {
return obj;
} else if (type === 'Boolean') {
return obj;
} else if (type === 'Array') {
const arr = [];
for (item of obj) {
if (typeof item === 'object') {
arr.push(deepCopy(item));
} else {
arr.push(item);
}
}
return arr;
} else if (type === 'Null') {
return null;
}
} const obj = {
a: 1,
b: {
bb: 1
},
d: [1, 2, { cc: '123' }]
} // const copy_obj = deepCopy(obj);
// console.log(obj === copy_obj)
// console.log(copy_obj);
// console.log(deepCopy(null))
/**
* 深拷贝优化版
*
* @param {*} source
* @returns {*}
*/
function deepClone2(source) {
let target;
console.log(source.constructor);
if (source.constructor === Array || source.constructor === Object) {
target = source.constructor === Array ? [] : {};
for (let key in source) {
if (source.hasOwnProperty(key)) {
if (source[key] && typeof source[key] === 'object') {
target[key] = deepClone2(source[key]);
} else {
target[key] = source[key];
}
}
}
} else {
target = source;
}
return target;
} console.log(deepClone2(function () { }))
console.log(deepClone2([]))
console.log(deepClone2(1))
console.log(deepClone2(obj))

JavaScript通过递归实现深拷贝的更多相关文章

  1. 关于JavaScript的浅拷贝和深拷贝

    在 JS 中有一些基本类型像是Number.String.Boolean,而对象就是像这样的东西{ name: 'Larry', skill: 'Node.js' },对象跟基本类型最大的不同就在于他 ...

  2. javascript篇-浅拷贝与深拷贝

    理解javascript 的浅拷贝与深拷贝,首先看一下js的数据类型: js有5种基本数据类型:undefined,null,boolean,number,string 还有一种复杂的数据类型(也叫引 ...

  3. 全面聊聊JavaScript的浅拷贝和深拷贝

    一.背景      首先我们可以看下面这段简单的代码: var obj = {name:'程序猿',sex:'男'}; var arr = ['程序猿','程序媛']; var copyobj = o ...

  4. Javascript中递归造成的堆栈溢出及解决方案

    关于堆栈的溢出问题,在Javascript日常开发中很常见,Google了下,相关问题还是比较多的.本文旨在描述如何解决此类问题. 首先看一个实例(当然你可以使用更容易的方式实现,这里我们仅探讨递归) ...

  5. 每天一个JavaScript实例-递归实现反转数组字符串

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  6. 递归实现深拷贝( 只要学过js递归,看不懂找我包会 )

    要用递归实现深拷贝,首先说说什么是深拷贝和浅拷贝 浅拷贝:一个值赋给另一个值,当原先的值不改变地址的情况下改变数据,另一个值跟着变 深拷贝:一个值赋给另一个值,当原先的值不改变地址的情况下改变数据,另 ...

  7. javascript之闭包,递归,深拷贝

    闭包 理解:a函数执行后return出b函数且b函数可以访问a函数的数据 好处:子函数存储在复函数内部,子函数执行完不会被自动销毁 坏处:占用内存比较大 ex: function bibao(){ v ...

  8. JavaScript中浅拷贝和深拷贝的区别

    JavaScript数据类型 基础数据类型:保存在栈内存中的简单数据段 ,有undefined,boolean,number,string,null 引用数据类型:Array,object,Funct ...

  9. javascript的浅拷贝和深拷贝

    1.浅拷贝:复制一份引用,所有引用对象都指向一份数据,并且都可以修改这份数据. 2.深拷贝(复杂):复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制. 这里画一个简单的图来加深理解: ...

  10. JavaScript的递归之更多例子

    更多例子 第二个递归的例子是求两个自然数的最大公约数(有没有回到令人怀念的中学时代).下面的程序用的是经典的辗转相除法. //greatest common divisor //假定a.b都是正整数 ...

随机推荐

  1. [Go] 结构体 嵌套 结构体指针 的含义

    举个例子:以下 FutureKline 这个结构体 包含了 Kline 结构体的指针,为什么不直接是 Kline 结构体. type Kline struct { Pair CurrencyPair ...

  2. Ingress-Controller高可用方案及多租户场景(21)

    一.Ingress-controller高可用 Ingress Controller 是集群流量的接入层,对它做高可用非常重要,可以基于 keepalive 实现 nginx-ingress-cont ...

  3. FFmpeg开发笔记(十九)FFmpeg开启两个线程分别解码音视频

    ​同步播放音视频的时候,<FFmpeg开发实战:从零基础到短视频上线>一书第10章的示例程序playsync.c采取一边遍历一边播放的方式,在源文件的音频流和视频流交错读取的情况下,该方式 ...

  4. 11.IO 流

    1.IO 流引入 概述:以应用程序为参照物,读取数据为输入流(Input),写数据为输出流(Output),大量输入输出数据简称 IO 流 原理: 2.IO 流的分类 读写的文件分类 二进制文件:打开 ...

  5. 16、数据库加固-mongo 加固

    1.指定日志与数据库存放位置 在配置文件中设置指向目录位置 自建配置文件:vim /usr/local/mongodb/etc/mongodb.conf dbpath=/data/db logpath ...

  6. MacOS安装gprMax教程

    原文发布于:https://blog.zhaoxuan.site/archives/19.html: 第一时间获取最新文章请关注博客个人站:https://blog.zhaoxuan.site. 1. ...

  7. WebKit中WTFMove实现

    WTFMove定义位置: WTF/Source/wtf/StdLibExtras.h,其定义如下: #define WTFMove(value) std::move<WTF::CheckMove ...

  8. spring-boot集成Quartz-job存储方式二RAM,改从json配置文件读取job配置

    前面第二种RAM方法已经可以满足单机使用需求了,但是本地调试和服务器应用会有冲突,因此将定时任务保存到本地json配置文件中,这样更灵活. 1.ApplicationInit类 package org ...

  9. vue中v-for说明

    v-if vs v-show区别v-if:每次显示与否,都会执行销毁和重建,渲染开销较大v-show:始终会被渲染并保留在DOM中.只是简单地切换display属性.频繁切换的时候用v-if,较少切换 ...

  10. JDK源码阅读-------自学笔记(六)(java.util.Arrays用法和描述浅析)

    工具类的使用 要多使用这个类,同时,很多算法包含其中,常见操作排序.查找.填充.打印等. 1.打印数组 ------Arrays.toString() 1 // 整型初始化 2 int[] integ ...