美文网首页我爱编程让前端飞Web前端之路
简述js的栈、堆、深拷贝、浅拷贝

简述js的栈、堆、深拷贝、浅拷贝

作者: EdmundChen | 来源:发表于2018-05-18 00:01 被阅读68次

一、栈(stack)和堆(heap)

  • stack为自动分配的内存空间,它由系统自动释放。
  • heap则是动态分配的内存,大小不定也不会自动释放。

二、基本类型和引用类型

  • 基本类型:存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配。
    5种基本数据类型有UndefinedNullBooleanNumberStringSymbol,它们是直接按值存放的,所以可以直接访问。
  • 引用类型:存放在堆(heap)内存中的对象,变量实际保存的是一个指针,这个指针指向堆(heap)的对象。每个空间大小不一样,要根据情况开进行特定的分配。
    当我们需要访问引用类型(如对象,数组,函数等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。

三、传值与传址

var a = [1,2,3,4,5];
var b = a; //传址 ,对象中传给变量的数据是引用类型的,会存储在堆中;
var c = a[0]; //传值,把对象中的属性/数组中的数组项赋值给变量,这时变量c是基本数据类型,存储在栈内存中;改变栈中的数据不会影响堆中的数据
//改变数值        
b[4] = 6;
c = 7;
console.log('a[4]', a[4]) // 6
console.log('a[0]', a[0]) // 1
console.log('c', c) // 7

传值与传址的区别。因为a是数组,属于引用类型,所以它赋予给b的时候传的是栈中的地址(相当于新建了一个不同名“指针”),而不是堆内存中的对象。而c仅仅是从a堆内存中获取的一个数据值,并保存在栈中。所以b修改的时候,会根据地址回到a堆中修改,c则直接在栈中修改,并且不能指向a堆内存中。


ddd.jpeg

JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用访问的。

四 扩展

1、const

简述: const声明一个只读的常量。一旦声明,常量的值就不能改变。
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。
基本类型的数据,值就保存在变量指向的那个栈(stack)地址,因此等同于常量。
引用类型的数据,变量的指向的栈(stack)地址,保存的是一个指针,const只能保证这个指针是固定的,至于指针指向的堆(heap)数据结构就完全不能控制了。所以一下代码是没有错误的;

const a = [];
a.push('school');

2、浅拷贝

在定义一个引用类型时,变量存放的往往只是一个指针地址。当我们使用对象拷贝时,如果属性是对象数组时,这时候传递的也只是一个地址。因此子对象在访问该属性时,会根据地址回溯到父对象指向的堆内存中,即父子对象发生了关联,两者的属性值会指向同一内存空间。

    const obj1 = {
      name:"张三",
      address:['乐山', '成都']
    }
    function clone(obj) {
      const obj2 = {};
      for (const key in obj) {
      obj2[key] = obj[key];
      }
      return obj2;
   }
    const obj2 = clone(obj1);
    obj2.age = '23';
    console.log('obj2.name', obj2.name);     //张三
    console.log('obj2.age', obj2.age);    // 23
    console.log('obj1.age', obj1.age);    //undefined

  obj2.address.push("德阳");
  console.log('obj2.address', obj2.address);  // ['乐山', '成都', '德阳']
  console.log('obj1.address', obj1.address);  // ['乐山', '成都', '德阳']
image.png

3、深拷贝

既然属性值类型是数组和或象时只会传址,那么我们就用递归来解决这个问题,把父对象中所有属于对象的属性类型都遍历赋给子对象即可。


image.png

参考文献: https://www.cnblogs.com/huangshikun/p/6510482.html

相关文章

  • 简述js的栈、堆、深拷贝、浅拷贝

    一、栈(stack)和堆(heap) stack为自动分配的内存空间,它由系统自动释放。 heap则是动态分配的内...

  • 对象的深拷贝与浅拷贝

    浅拷贝和深拷贝都是对于JS中的引用类型而言的,浅拷贝就只是复制对象的引用(堆和栈的关系,简单类型Undefined...

  • js 深拷贝 vs 浅拷贝(本篇博客摘抄子掘金‘sunshine

    链接本文主要讲一下 js 的基本数据类型以及一些堆和栈的知识和什么是深拷贝、什么是浅拷贝、深拷贝与浅拷贝的区别,以...

  • OC由浅入深系列 之 深浅拷贝

    一、什么是深拷贝,浅拷贝? 在堆中产生一个副本的拷贝操作称为深拷贝,在栈中声名一个指针指向对象的堆地址称为浅拷贝。...

  • JS中的深拷贝与浅拷贝

    知乎:js中的深拷贝和浅拷贝? 掘金: js 深拷贝 vs 浅拷贝 前言 首先深拷贝与浅拷贝只针对 Object,...

  • js浅拷贝深拷贝

    js浅拷贝,深拷贝的简单实现 基础数据 浅拷贝 深拷贝

  • js的深拷贝和浅拷贝

    学习之前,先了解下堆和栈知识,js 的数据类型 堆和栈的区别 其实深拷贝和浅拷贝的主要区别就是其在内存中的存储类型...

  • js底层数据类型

    js底层数据类型 堆和栈的区别 其实深拷贝和浅拷贝的主要区别就是其在内存中的存储类型不同。 堆和栈都是内存中划分出...

  • 浅拷贝与深拷贝

    一、内存 我们都知道数据存放内存中,基本数据在栈内存,引用数据指针在栈内存实体在堆内存 二、深拷贝与浅拷贝 深拷贝...

  • 浅拷贝和深拷贝

    本文参考:JavaScript中的浅拷贝和深拷贝js 深拷贝 vs 浅拷贝深入剖析 JavaScript 的深复制...

网友评论

    本文标题:简述js的栈、堆、深拷贝、浅拷贝

    本文链接:https://www.haomeiwen.com/subject/yebbdftx.html