JavaScript中的浅拷贝与深拷贝
  学了这么长时间的JavaScript想必大家对浅拷贝和深拷贝还不太熟悉吧,今天在项目中既然用到了,早晚也要理清一下思路了,在了解之前,我们还是先从JavaScript的数据类型存放的位置 堆栈开始说起吧!           

现在我们带着问题来学习!

一:什么是堆栈?

  我们都知道:在计算机领域中,堆栈是两种数据结构,它们只能在一端(称为栈顶(top))对数据项进行插入和删除。

堆:队列优先,先进先出;由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
栈:先进后出;动态分配的空间 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
以上都属于计算机基础部分,在此都不详细赘述了,下面我们联系JavaScript来剖析一下堆栈。
二:JavaScript中的基本类型和引用类型与堆栈有什么联系?
JavaScript的数据类型分为两大种:
1. 基本类型Undefined、Null、Boolean、Number 和 String,这5中基本数据类型可以直接访问,他们是按照值进行分配的,存放在栈(stack)内存中的简单数据段,数据大小确定,内存空间大小可以分配。
2. 引用类型:即存放在堆(heap)内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。
  以上我们知道了什么是堆栈,和JavaScript的数据类型,下面我们根据js的数据类型来说明一下他们的拷贝情况:

var obj1 = {name:'bangbang',age:18};
var b = obj1;
var c = obj1.age; console.log(b.name); //bangbang
console.log(c); //
//改变b和c的值
b.name = 'yanniu';
c = 22;
console.log(obj1.name); //yanniu
console.log(obj1.age); //

 以上看出:当我们改变b的数据的时候,我们看到了obj1.name的数据也在改变,但是我们改变c的数据的时候发现,obj1.age的值没有变化,这说明了:b和obj1变量操作的是同一个对象,c和obj1完全独立的。图示如下:

三:什么是浅拷贝?
  根据上面的陈述,基本类型拷贝的时候只是在内存中又开辟了新的空间,和它的父元素(再次我们称被拷贝的对象为父元素)属于 互不想干的东西,因此深浅拷贝是相对于引用类型的,以便于我们对引用类型父对象的保存! 嘿嘿!我们接着看!
例如:

var father1 = {name:'shangdi',age:1000,job:['teacher','cook']};
//浅拷贝函数
function copy(obj){
var childs = {};
for(var key in obj){
childs[key] = obj[key];
}
return childs;
}
var child1 = copy(father1);
console.log(child1); //{ name: 'shangdi', age: 1000 }
console.log(typeof child1); //object //改变子对象的name属性,发现对父对象的name没有影响 哈哈!
child1.name = 'bangbang';
console.log(father1); //{ name: 'shangdi', age: 1000 }
console.log(child1); //{ name: 'bangbang', age: 1000 } //注意:这次改变子对象的job属性也就是改变数组,
//发现对父对象的job竟然有影响,吓死宝宝了,那怎么办呢,那这个copy有什么用呢是吧!
child1.job.push('programer');
console.log(father1); //{ name: 'shangdi',age: 1000,job: [ 'teacher', 'cook', 'programer' ] }
console.log(child1); //{ name: 'shangdi',age: 1000,job: [ 'teacher', 'cook', 'programer' ] }

由上面可分析:浅拷贝的时候,当我们改变子对象的数组的时候,父对象竟然也跟着改变,也就是说:子对象和父对象在浅拷贝的时候他们指向同一个内存的数组:由图所示:

如果我们想让子对象的拷贝和父对象没有一点关联,那么我们就必须用到深度拷贝!嘿嘿!儿子也不能完全跟着爹长啊!

四:什么是深度拷贝?
深度拷贝就是把父对象拷贝到子对象上,而且两者的内存和以后的操作都互不影响的拷贝!

function deepCopy(obj){
var o;
switch(typeof obj){
case 'undefined': break;
case 'string' : o = obj + '';break;
case 'number' : o = obj - 0;break;
case 'boolean' : o = obj;break;
case 'object' :
if(obj === null){
o = null;
}else{
if(obj instanceof Array){
o = [];
for(var i = 0, len = obj.length; i < len; i++){
o.push(deepCopy(obj[i]));
}
}else{
o = {};
for(var k in obj){
o[k] = deepCopy(obj[k]);
}
}
}
break;
default: o = obj;break;
}
return o;
}

下面是一些克隆的方法供大家参考,不过他们有区别,自己试验:
方法二:最简单的

function deepCopy(obj) {
return JSON.parse(JSON.stringify(obj));
}

方法三:

function deepCopy(obj){
var newobj, obj;
if (obj.constructor == Object){
newobj = new obj.constructor();
}else{
newobj = new obj.constructor(obj.valueOf());//valueOf()方法返回 Array 对象的原始值
}
for(var key in obj){
if ( newobj[key] != obj[key] ){
if ( typeof(obj[key]) == 'object' ){
newobj[key] = deepCopy(obj[key]);
}else{
newobj[key] = obj[key];
}
}
}
newobj.toString = obj.toString;
newobj.valueOf = obj.valueOf;
return newobj;
}

方法四:

var cloneObj = function(obj){
var str, newobj = obj.constructor === Array ? [] : {};
if(typeof obj !== 'object'){
return;
} else if(window.JSON){
str = JSON.stringify(obj), //系列化对象
newobj = JSON.parse(str); //还原
} else {
for(var i in obj){
newobj[i] = typeof obj[i] === 'object' ?
cloneObj(obj[i]) : obj[i];
}
}
return newobj;
};

方法五:(JavaScript面向对象编程指南)

function deepCopy(p,c){
c = c || {};
for (var i in p){
if(p.hasOwnProperty(i)){
if(typeof p[i] === 'object'){
c[i] = Array.isArray(p[i]) ? [] : {};
deepCopy(p[i],c[i]);
}else{
c[i] = p[i];
}
}
}
return
}
原文来自:https://blog.csdn.net/flyingpig2016/article/details/52895620
 

深入理解JavaScript中的堆与栈 、浅拷贝与深拷贝的更多相关文章

  1. 理解JavaScript中的堆和栈

    这里先说两个概念:1.堆(heap)2.栈(stack)堆 是堆内存的简称.栈 是栈内存的简称.说到堆栈,我们讲的就是内存的使用和分配了,没有寄存器的事,也没有硬盘的事.各种语言在处理堆栈的原理上都大 ...

  2. 设计模式之原型模式(深入理解OC中的NSCopying协议以及浅拷贝、深拷贝)

    原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.原型模式其实就是从一个对象再创建另一个可定制的对象,而且不需知道任何创建的细节. 比如说,有一个Person类,有firstN ...

  3. JavaScript 数据结构与算法之美 - 栈内存与堆内存 、浅拷贝与深拷贝

    前言 想写好前端,先练好内功. 栈内存与堆内存 .浅拷贝与深拷贝,可以说是前端程序员的内功,要知其然,知其所以然. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 JavaScri ...

  4. 栈 堆 stack heap 堆内存 栈内存 内存分配中的堆和栈 掌握堆内存的权柄就是返回的指针 栈是面向线程的而堆是面向进程的。 new/delete and malloc/ free 指针与内存模型

    小结: 1.栈内存 为什么快? Due to this nature, the process of storing and retrieving data from the stack is ver ...

  5. Java中的堆和栈的区别

    当一个人开始学习Java或者其他编程语言的时候,会接触到堆和栈,由于一开始没有明确清晰的说明解释,很多人会产生很多疑问,什么是堆,什么是栈,堆和栈有什么区别?更糟糕的是,Java中存在栈这样一个后进先 ...

  6. java中的堆、栈、常量池

    java中的堆.栈.常量池 分类: java2010-01-15 03:03 4248人阅读 评论(5) 收藏 举报 javastring编译器jvm存储equals Java内存分配: 1. 寄存器 ...

  7. 理解 JavaScript 中的 this

    前言 理解this是我们要深入理解 JavaScript 中必不可少的一个步骤,同时只有理解了 this,你才能更加清晰地写出与自己预期一致的 JavaScript 代码. 本文是这系列的第三篇,往期 ...

  8. java中的堆与栈

    Java 中的堆和栈 Java把内存划分成两种:一种是栈内存,一种是堆内存. 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配 . 当在一段代码块定义一个变量时,Java就在栈中 ...

  9. 理解JavaScript中的原型继承(2)

    两年前在我学习JavaScript的时候我就写过两篇关于原型继承的博客: 理解JavaScript中原型继承 JavaScript中的原型继承 这两篇博客讲的都是原型的使用,其中一篇还有我学习时的错误 ...

随机推荐

  1. CSS定位属性position相关介绍

    position属性用来定义元素的定位方式. 定位相关属性值 1.static 默认值 2.absolute 绝对定位 3.fixed 固定定位 4.relative 相对定位 5.sticky 粘性 ...

  2. NumPy——统计函数

    引入模块import numpy as np 1.numpy.sum(a, axis=None)/a.sum(axis=None) 根据给定轴axis计算数组a相关元素之和,axis整数或元组,不指定 ...

  3. 关于图数据库HugeGraph的百万,千万,亿量级测试

    1.Hugegraph测试硬件 1.1.本机硬件 本机测试hugeGraph版本:0.10.4 后置存储数据库:rocksdb,1TB的普通硬盘 1.2.测试服务器硬件 测试服务器hugegraph版 ...

  4. 使用webpack从0搭建多入口网站脚手架,可复用导航栏/底部通栏/侧边栏,根据页面文件自动更改配置,支持ES6/Less

    之前只知道webpack很强大,但是一直没有深入学习过,这次从头看了一下教程,然后从0开始搭建了一个多入口网站的开发脚手架,期间遇到过很多问题,所以有心整理一下,希望能给大家一点帮助. 多HTML网站 ...

  5. vue学习笔记(四)

    一.vue-router 1.简介 我们经常使用vue开发单页面应用程序(SPA).在开发SPA过程中,路由是必不可少的部分,vue的官方推荐是vue-router.单页面应用程序看起来好像是一个页面 ...

  6. 基于Vue的机器学习平台前端

    项目演示地址:http://vidanao.com/ml>注意1:前端兼容性不太好,360浏览器比较兼容; >注意2:此vidanao.com也是我的个人博文主页,但目前还没部署 源码地址 ...

  7. js数组冒泡排序、快速排序、插入排序

    1.冒泡排序 //第一种 function bubblesort(ary){ for(var i=0;i<ary.length-1;i++){ for(var j=0;j<ary.leng ...

  8. Markdown语法说明及常用软件推荐(附链接)

    Markdown语法同样支持HTML标签 以下所有字符均为英文字符 标题 标题级别由#决定,一个为一级 样例 # 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 ##### 五级标题 ...

  9. Vue的模板内换行问题

    在用vue的模板{{}}进行渲染文本时候,字符串换行不起作用,后使用ES6的模板字符串进行换行仍然不起作用,解决方法: <div>{{str}}</div> 可换为用v-htm ...

  10. 基于VR三维全景的虚拟展馆展览实现

    VR三维全景虚拟现实技术的应用,能够通过全方位互动式来还原真实场景,令人产生一种身临其境的感觉,由于三维全景虚拟现实技术具有一定应用优势,其在企业与院校展示.建筑规划展示.酒店宾馆展示等方面都逐步得到 ...