zoukankan      html  css  js  c++  java
  • js中的堆内存和栈内存

    我们常常会听说什么栈内存、堆内存,那么他们到底有什么区别呢,在js中又是如何区分他们的呢,今天我们来看一下。

    一、栈内存和堆内存的区分

    一般来说,栈内存主要用于存储各种基本类型的变量,包括Boolean、Number、String、Undefined、Null...以及对象变量的指针,这时候栈内存给人的感觉就像一个线性排列的空间,每个小单元大小基本相等,栈内存中的变量一般都是已知大小或者有范围上限的,算作一种简单存储。

    堆内存主要负责像对象Object这种变量类型的存储,堆内存存储的对象类型数据对于大小这方面,一般都是未知的,(所以这大概也是为什么null作为一个object类型的变量却存储在栈内存中的原因)。

    来一张图感受一下:

    二、测试

    Ⅰ.基本数据类型

            /* 基本数据类型 */
            var a = 1;
            var b = 1;
            console.log(a === b);//true
    
            var c = '桔子桑';
            var d = '桔子桑';
            console.log(c === d);//true

    基本数据类型,因为都是存在栈内存中的,以上面的int为例:

    var a = 1;变量 a 存在栈内存中,他的值是基本数据类型(int),自然也是在栈内存中,栈内存有没有1?没有那就拿出一块内存存1,这个变量a指向这块值为1的栈内存地址;

    var b = 1;同理,变量 b 也是在栈内存中的,但是赋值的时候,发现,栈内存有一块地址存着int型的值1,那么就直接指向这块栈内存了;

    所以最终 a === b 是 true;

    Ⅱ.new 关键字生成的对象

            /* new关键字 */
            var a = new String('桔子桑');
            var b = new String('桔子桑');
            console.log(a === b);//fasle

    new关键字生成的对象都是存在于堆内存中的,上述代码中:

    var a = new String('桔子桑');变量 a 存在于栈内存中,他的值是一个指针,这个指针指向堆内存中的一个对象!

     附上一段C代码,方便理解

    int  a = 20;    /* 实际变量的声明 */
    
    int  * ip;            /* 指针变量的声明 */
     
    ip = &a;        /* 在指针变量中存储 变量a 的地址 */

    所以我们应该这么理解:

    普通变量的值类型是基本数据类型,指向栈内存中的一块地址;

    引用类型变量的值是指针,指向堆内存中的一块地址。

    Ⅲ.指针的赋值(引用类型)

            /* 指针赋值 */
            var a = new String('桔子桑');
            var b = a;
            console.log(a === b);//true

    我们看到,指针型变量 a 的值是一个指针,指向堆内存中一块地址;

    然后 又定义了一个变量 b ,他的值等于 a,a 的值是什么?a 的值是一个指针啊,那么变量 b 就等于这个指针,自然也是指向堆内存的那一块地址咯。

    图示:

    Ⅳ.const关键字

    我们知道const关键字用来定义一个常量,

    const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。

    对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个栈内存地址,因此等同于常量。

    但对于复合类型的数据(主要是对象和数组),变量指向的栈内存地址,保存的只是一个栈内存指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。

    所以,const保证的是栈内存这边变量与其值不能发生改变,所以对于复合类型,指针指向的堆内存中存的数据结构能否改变是左右不了的。

            /* const关键字 */
            const a = 1;
            a = 2;
    
            const b = {
                name:'jack'
            };
            b.name = 'tom';

    对于前者,因为常量 a 和他的值都是在栈内存中的,不能更改,手动修改只会报错:

    而对于后者,因为常量 b 的值是一个指针,这个指针由于存在于栈内存,所以他的指向是不能更改的(堆内存地址),但是对应堆内存地址中存的数据结构(存了一个对象)是可以更改的。

  • 相关阅读:
    Layui 数据表格显示图片,鼠标滑过图片放大
    ModuleNotFoundError: No module named redis
    Layui 数据表格特定数据行变色
    Qt下QMainWindow内部QTableView不能自适应大小
    android-启动另外一个Activity
    sqlite获取表字段
    Apache下更改.htaccess文件名称
    QTableView的indexAt使用方法
    Qt分割线
    QTableView排序
  • 原文地址:https://www.cnblogs.com/eco-just/p/11119830.html
Copyright © 2011-2022 走看看