我的编程空间,编程开发者的网络收藏夹
学习永远不晚

JavaScript怎么实现深拷贝

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

JavaScript怎么实现深拷贝

本篇内容主要讲解“JavaScript怎么实现深拷贝”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript怎么实现深拷贝”吧!

什么是浅拷贝

关于浅拷贝的概念,我在网上看到一种说法,直接上代码。

var person = {name: "Jason", age: 18, car: {brand: "Ferrari", type: "430"}};var person1 = person;       //他们认为这是浅拷贝

但是我个人认为,上面这个根本不涉及拷贝,只是一个简单的引用赋值。以我的理解,浅拷贝应该是不考虑对象的引用类型的属性,只对当前对象的所有成员进行拷贝,代码如下:

function copy(obj){    var objCopy = {};    for(var key in obj){        objCopy[key] = obj[key];    }    return objCopy;}var person = {name: "Jason", age: 18, car: {brand: "Ferrari", type: "430"}};var personCopy = copy(person);

上面这段代码中,person对象拥有两个基本类型的属性nameage,一个引用类型的属性car,当使用如上方法进行拷贝的时候,nameage属性会被正常的拷贝,但是car属性,只会进行引用的拷贝,这样会导致拷贝出来的对象personCopyperson会共用一个car对象。这样就是所谓的浅拷贝。

什么是深拷贝

深拷贝的就是在拷贝的时候,需要将当前要拷贝的对象内的所有引用类型的属性进行完整的拷贝,也就是说拷贝出来的对象和原对象之间没有任何数据是共享的,所有的东西都是自己独占的一份。

如何实现深拷贝

实现深拷贝需要考虑如下几个因素:

  • 传入的对象是使用对象字面量{}创建的对象还是由构造函数生成的对象

  • 如果对象是由构造函数创建出来的,那么是否要拷贝原型链上的属性

  • 如果要拷贝原型链上的属性,那么如果原型链上存在多个同名的属性,保留哪个

  • 处理循环引用的问题

第三方库实现深拷贝

jQuery的$.extend()

我们可以通过$.extend()方法来完成深复制。值得庆幸的是,我们在jQuery中可以通过添加一个参数来实现递归extend。调用$.extend(true, {}, ...)就可以实现深复制,参考下面的例子:

var x = {    a: 1,    b: { f: { g: 1 } },    c: [ 1, 2, 3 ]};var y = $.extend({}, x),          //shallow copy    z = $.extend(true, {}, x);    //deep copyy.b.f === x.b.f       // truez.b.f === x.b.f       // false

但是jQuery的这个$.extend()方法,有弊端,什么弊端呢?我们看下面的例子:

var objA = {};var objB = {};objA.b = objB;objB.a = objA;$.extend(true,{},a);//这个时候就出现异常了//Uncaught RangeError: Maximum call stack size exceeded(…)

也就是说,jQuery中的$.extend()并没有处理循环引用的问题。

使用JSON对象实现深拷贝

使用JSON全局对象的parsestringify方法来实现深复制也算是一个简单讨巧的方法。

function jsonClone(obj) {    return JSON.parse(JSON.stringify(obj));}var clone = jsonClone({ a:1 });

然而使用这种方法会有一些隐藏的坑,它能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。

自己造轮子

下面我们给出一个简单的解决方案,当然这个方案是参考别人的方式来实现的。希望对大家有用。

var clone = (function() {    //这个方法用来获取对象的类型 返回值为字符串类型 "Object RegExp Date Array..."    var classof = function(o) {        if (o === null) {            return "null";        }        if (o === undefined) {            return "undefined";        }        // 这里的Object.prototype.toString很可能用的就是Object.prototype.constructor.name        // 这里使用Object.prototype.toString来生成类型字符串        var className = Object.prototype.toString.call(o).slice(8, -1);        return className;    };    //这里这个变量我们用来存储已经保存过的属性,目的在于处理循环引用的问题    var references = null;    //遇到不同类型的对象的处理方式    var handlers = {        //正则表达式的处理        'RegExp': function(reg) {            var flags = '';            flags += reg.global ? 'g' : '';            flags += reg.multiline ? 'm' : '';            flags += reg.ignoreCase ? 'i' : '';            return new RegExp(reg.source, flags);        },        //时间对象处理        'Date': function(date) {            return new Date(+date);        },        //数组处理 第二个参数为是否做浅拷贝        'Array': function(arr, shallow) {            var newArr = [],            i;            for (i = 0; i < arr.length; i++) {                if (shallow) {                    newArr[i] = arr[i];                } else {                    //这里我们通过reference数组来处理循环引用问题                    if (references.indexOf(arr[i]) !== -1) {                        continue;                    }                    var handler = handlers[classof(arr[i])];                    if (handler) {                        references.push(arr[i]);                        newArr[i] = handler(arr[i], false);                    } else {                        newArr[i] = arr[i];                    }                }            }            return newArr;        },        //正常对象的处理 第二个参数为是否做浅拷贝        'Object': function(obj, shallow) {            var newObj = {}, prop, handler;            for (prop in obj) {                //关于原型中属性的处理太过复杂,我们这里暂时不做处理                //所以只对对象本身的属性做拷贝                if (obj.hasOwnProperty(prop)) {                    if (shallow) {                        newObj[prop] = obj[prop];                    } else {                        //这里还是处理循环引用的问题                        if (references.indexOf(obj[prop]) !== -1) {                            continue;                        }                        handler = handlers[classof(obj[prop])];                        //如果没有对应的处理方式,那么就直接复制                        if (handler) {                            references.push(obj[prop]);                            newObj[prop] = handler(obj[prop], false);                        } else {                            newObj[prop] = obj[prop];                        }                    }                }            }            return newObj;        }    };    return function(obj, shallow) {        //首先重置我们用来处理循环引用的这个变量        references = [];        //我们默认处理为浅拷贝        shallow = shallow === undefined ? true : false;        var handler = handlers[classof(obj)];        return handler ? handler(obj, shallow) : obj;    };}());(function() {    //下面是一些测试代码    var date = new Date();    var reg = /hello word/gi;    var obj = {        prop: 'this ia a string',        arr: [1, 2, 3],        o: {            wow: 'aha'        }    };    var refer1 = {        arr: [1, 2, 3]    };    var refer2 = {        refer: refer1    };    refer1.refer = refer2;    var cloneDate = clone(date, false);    var cloneReg = clone(reg, false);    var cloneObj = clone(obj, false);    alert((date !== cloneDate) && (date.valueOf() === cloneDate.valueOf()));    alert((cloneReg !== reg) && (reg.toString() === cloneReg.toString()));    alert((obj !== cloneObj) && (obj.arr !== cloneObj.arr) && (obj.o !== cloneObj.o) && (JSON.stringify(obj) === JSON.stringify(cloneObj)));    clone(refer2, false);    alert("I'm not dead yet!");    // Output:    // true    // true    // true    // I'm not dead yet!}());

到此,相信大家对“JavaScript怎么实现深拷贝”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

JavaScript怎么实现深拷贝

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

JavaScript怎么实现深拷贝

本篇内容主要讲解“JavaScript怎么实现深拷贝”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript怎么实现深拷贝”吧!什么是浅拷贝关于浅拷贝的概念,我在网上看到一种说法,直接
2023-06-27

JavaScript深拷贝与浅拷贝实现详解

深拷贝和浅拷贝是面试中经常出现的,主要考察对基本类型和引用类型的理解深度,这篇文章主要给大家介绍了关于js深拷贝和浅拷贝的相关资料,需要的朋友可以参考下
2022-11-13

怎么在JavaScript中实现深拷贝

怎么在JavaScript中实现深拷贝?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Java有哪些集合类Java中的集合主要分为四类:1、List列表:有序的,
2023-06-14

JavaScript浅拷贝与深拷贝如何实现

这篇文章主要介绍“JavaScript浅拷贝与深拷贝如何实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JavaScript浅拷贝与深拷贝如何实现”文章能帮助大家解决问题。在 JavaScript
2023-06-27

JS怎么实现深拷贝和浅拷贝

这篇文章主要介绍“JS怎么实现深拷贝和浅拷贝”,在日常操作中,相信很多人在JS怎么实现深拷贝和浅拷贝问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JS怎么实现深拷贝和浅拷贝”的疑惑有所帮助!接下来,请跟着小编
2023-06-30

Java的深拷贝和浅拷贝怎么实现

这篇文章主要介绍“Java的深拷贝和浅拷贝怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java的深拷贝和浅拷贝怎么实现”文章能帮助大家解决问题。关于Java的深拷贝和浅拷贝,简单来说就是创
2023-06-26

怎么在JavaScript中实现对象深拷贝

这篇文章给大家介绍怎么在JavaScript中实现对象深拷贝,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。JavaScript是什么JS是JavaScript的简称,它是一种直译式的脚本语言,其解释器被称为JavaSc
2023-06-14

JavaScript深拷贝与浅拷贝是什么

这篇文章主要介绍了JavaScript深拷贝与浅拷贝是什么,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1 浅拷贝概念深拷贝和浅拷贝是只针对Object和Array这样的引用
2023-06-29

分析JavaScript浅拷贝和深拷贝

本篇内容主要讲解“分析JavaScript浅拷贝和深拷贝”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析JavaScript浅拷贝和深拷贝”吧!一、直接赋值对象是引用类型,如果直接赋值给另外一
2023-06-25

JavaScript中深拷贝与浅拷贝实例运用

这篇文章主要介绍了JavaScript中深拷贝与浅拷贝实例运用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JavaScript中深拷贝与浅拷贝实例运用文章都会有所收获,下面我们一起来看看吧。1 浅拷贝概念深拷
2023-06-29

JavaScript中的深拷贝如何实现

今天小编给大家分享一下JavaScript中的深拷贝如何实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。深拷贝的最终实现这
2023-07-04

JavaScript中的浅拷贝和深拷贝原理与实现浅析

这篇文章主要介绍了JavaScript中的浅拷贝和深拷贝原理与实现,JavaScript中的浅拷贝和深拷贝指的是在复制对象(包括对象、数组等)时,是否只复制对象的引用地址或者在复制时创建一个新的对象
2023-05-17

JavaScript深拷贝与浅拷贝原理深入探究

深拷贝和浅拷贝是面试中经常出现的,主要考察对基本类型和引用类型的理解深度,这篇文章主要给大家介绍了关于js深拷贝和浅拷贝的相关资料,需要的朋友可以参考下
2022-11-13

Python中怎么实现深浅拷贝

这篇文章将为大家详细讲解有关Python中怎么实现深浅拷贝,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、深浅copy 1. 赋值运算l1 = [1, 2, 3, [22, 33]]
2023-06-15

Vue浅拷贝和深拷贝实现方案

在理解浅拷贝和深拷贝浅前,必须先理解基本数据类型和引用数据类型的区别,这篇文章主要介绍了Vue浅拷贝和深拷贝实现方案及区别对比分析,需要的朋友可以参考下
2023-03-03

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录