博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入JavaScript中深拷贝和浅拷贝
阅读量:7222 次
发布时间:2019-06-29

本文共 4420 字,大约阅读时间需要 14 分钟。

深拷贝和浅拷贝问题的本质还是不同数据类型的存储方式差异,尤其是引用数据类型的特殊。

图片描述

现分别对赋值、浅拷贝、深拷贝做深入研究:

1.赋值

原理:直接将对象指针直接赋值给另一个变量

代码

let developer = {    title: 'Frontend',    basic: {        html: '5',        css: '3',        js: 'es6'    },    frameworks: ['React', 'Vue', 'AngularJS'],    summary: function(){        console.log('I am FE developer');    }};let newDeveloper = developer;console.log(newDeveloper);//基本类型:改变原对象newDeveloper.title = 'Frontend Leader';console.log(developer.title); // Frontend Leader//对象:改变原对象newDeveloper.basic.http = '2.0';console.log(developer.basic.http); // 2.0newDeveloper.basic.js = 'es5';console.log(developer.basic.js); // es5//数组:改变原对象newDeveloper.frameworks.push('Angular');console.log(developer.frameworks); // [ 'React', 'Vue', 'AngularJS', 'Angular' ]//函数:改变原对象newDeveloper.summary = function () {    console.log('I like FE development');};developer.summary(); // I like FE development

2.浅拷贝

原理:遍历对象的每个属性进行逐个拷贝

实现方式

  • 方式1:遍历并复制
  • 方式2:Object.assign()

代码

let developer = {    title: 'Frontend',    basic: {        html: '5',        css: '3',        js: 'es6'    },    frameworks: ['React', 'Vue', 'AngularJS'],    summary: function(){        console.log('I am FE developer');    }};/** 方式1:逐个复制** */function cloneInShallow(source) {    let target = {};    for (prop in source){        target[prop] = source[prop];    }    return target}let newDeveloper = cloneInShallow(developer);/** 方式2:Object.assign()** */// let newDeveloper = Object.assign({}, developer);console.log(newDeveloper);//基本类型:不改变原对象newDeveloper.title = 'Frontend Leader';console.log(developer.title); // Frontend// 对象:改变原对象newDeveloper.basic.http = '2.0';console.log(developer.basic.http); // 2.0newDeveloper.basic.js = 'es5';console.log(developer.basic.js); // es5//数组:改变原对象newDeveloper.frameworks.push('Angular');console.log(developer.frameworks); // [ 'React', 'Vue', 'AngularJS', 'Angular' ]//函数:不改变原对象newDeveloper.summary = function () {    console.log('I like FE development');};developer.summary(); // I am FE developer

3.深拷贝

原理:使用递归,遍历每一个对象属性进行拷贝

实现方式

  • 方式1: 纯手工打造回调函数
  • 方式2: JSON.parse(JSON.stringify(obj))
  • 方式3: 借助jQuery
  • 方式4: 借助lodash

代码

let developer = {    title: 'Frontend',    basic: {        html: '5',        css: '3',        js: 'es6'    },    frameworks: ['React', 'Vue', 'AngularJS', {node: 'express'}],    summary: function(){        console.log('I am FE developer');    }};/** 方式1: 纯手工打造* */function cloneInDeep(source) {    if(source && typeof source === 'object'){        let target = {};        for (let prop in source){            let value = source[prop];            if(Array.isArray(value)){                let newArray = [];                value.forEach(function (item, index) {                    if(Array.isArray(item) || Object.getPrototypeOf(item) === Object.prototype){                        newArray.push(cloneInDeep(item))                    }else{                        newArray.push(item)                    }                });                target[prop] = newArray;            }else if(Object.getPrototypeOf(value) === Object.prototype){                target[prop] = cloneInDeep(value);            }else{                target[prop] = value;            }        }        return target    }else{        throw new Error('source is not object!')    }}let newDeveloper = cloneInDeep(developer);/** 方式2: JSON.parse(JSON.stringify(obj))* 弊端:会抛弃对象的constructor* 适用:能够被json直接表示的数据结构,对象中只包含number、string、boolean、array、扁平对象* 不适用:含有function、regexp* */// let newDeveloper = JSON.parse(JSON.stringify(developer));/** 方式3: jQuery* */let $ = require('jquery');// let newDeveloper = $.extend({}, developer);/** 方式4: lodash* */let _ = require('lodash');// let newDeveloper = _.cloneDeep(developer);console.log(newDeveloper);//基本类型:不改变原对象newDeveloper.title = 'Frontend Leader';console.log(developer.title); // Frontend// 对象:不改变原对象newDeveloper.basic.http = '2.0';console.log(developer.basic.http); // undefinednewDeveloper.basic.js = 'es5';console.log(developer.basic.js); // es6//数组:不改变原对象newDeveloper.frameworks.push('Angular');console.log(developer.frameworks); // [ 'React', 'Vue', 'AngularJS' , { node: 'express' } ]newDeveloper.frameworks[3].node = 'koa';console.log(developer.frameworks); // [ 'React', 'Vue', 'AngularJS' , { node: 'express' } ]//函数:不改变原对象newDeveloper.summary = function () {    console.log('I like FE development');};developer.summary(); // I am FE developer

涉及的知识点:

  • 数据类型及存储机制
  • for...in...遍历,枚举属性
  • 递归
  • 对象和数组的判断

转载地址:http://vikfm.baihongyu.com/

你可能感兴趣的文章
WordPress 5.2 Beta 3 发布,要求 PHP 5.6.20 以上版本
查看>>
通通连起来——无处不在的流
查看>>
互联网+时代,看云计算如何改变传统行业
查看>>
ZFS ARC & L2ARC zfs-$ver/module/zfs/arc.c
查看>>
c++类默认拷贝构造函数---浅复制
查看>>
2019年最火热的Golang项目
查看>>
可实现RSSD云硬盘120万IOPS的SPDK IO路径优化实践
查看>>
Vue项目部署遇到的坑(你肯定会遇到!)
查看>>
资源分享计划第三期 0511
查看>>
awk 文本处理
查看>>
【JSConf EU 2018】主题总结 (部分主题已有中文文章)
查看>>
JavaScript面向对象名词详解
查看>>
Java设计模式学习 - 责任链模式
查看>>
JVM,DVM,ART
查看>>
webgl滤镜--会呼吸的痛
查看>>
用Go语言实现微信支付SDK
查看>>
oauth2在php实践
查看>>
LeetCode.914 卡牌分组
查看>>
填坑app:compileDebugJavaWithJavac
查看>>
Android 100+行实现本地跳一跳辅助(不需要连接电脑)
查看>>