js变量存在的两种类型(原始值,引用值)

    xiaoxiao2021-03-25  121

    js变量存在的两种类型(原始值,引用值)

    由于最近面试问到过这个问题,所以特定补一下这里面的知识:

    原始值类型:Undefined、Null、Boolean、Number 和 String 型;存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置;

    引用值类型:object,Array , 函数;存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存处。

    在这里大家有必要理解什么是堆,栈,堆栈,队列是什么?

    堆栈是什么?

    堆栈是一个在计算机科学中经常使用的抽象数据类型。堆栈中的物体具有一个特性: 最后一个放入堆栈中的物体总是被最先拿出来, 这个特性通常称为后进先出(LIFO)队列。 堆栈中定义了一些操作。 两个最重要的是PUSH和POP。 PUSH操作在堆栈的顶部加入一 个元素。POP操作相反, 在堆栈顶部移去一个元素, 并将堆栈的大小减一。通俗的来讲就是后进先出的方式。例如:

    var list=[]; list.push('1') list.push('2') list.push('3') list.push('4') console.log(list) //[1,2,3,4] list.pop() //4

    既然是抽象数据类型 那肯定会有自己的内存吧!

    什么是堆?

    是为动态分配预留的内存空间;你可以在任何时候分配和释放它。这样使得跟踪哪部分堆已经被分配和被释放变的异常复杂;有许多定制的堆分配策略用来为不同的使用模式下调整堆的性能,存放数组以及函数对象引用值。

    什么是栈?

    由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等,存放一些基础类型。

    为什么会有栈内存和堆内存之分?

    通常与垃圾回收机制有关。为了使程序运行时占用的内存最小。 当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁了。因此,所有在方法中定义的变量都是放在栈内存中的; 当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(因为对象的创建成本通常较大),这个运行时数据区就是堆内存。堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见),则这个对象依然不会被销毁,只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。

    什么是队列?

    队列只能在队头做删除操作,在队尾做插入操作.而栈只能在栈顶做插入和删除操作,与堆栈相反,队列遵循先进先出的法则, var list=[]; list.unshift('1') list.unshift('2') list.unshift('3') list.unshift('4') console.log(list) //[4,3,2,1] list.shift() //4

    看完堆栈与队列知识现在回到,原始值与引用值上面。看下面代码

    代码块

    例如:

    var a=1; var b=a; a=3; console.log(b) // 1 var Array_a=[1,2,3,4] var Array_b=Array_a; Array_b[1]=Array_a[2]; console.log(Array_a) //[1,3,3,4] console.log(Array_b) //[1,3,3,4]

    比较上面两种你会发现不一样,a=3,不会改变b的值,b的值改变更不会改变a的值,但是下面的数组却不一样Array_b却能改变Array_a里面的值,原因是数组对象保存在堆内存当中,只是暴露了一个地址在栈当中,这个地址就是变量Array_a以及后来的Array_b,这两个都是指向堆内存当中同一个数组,所以当你改变任何一个数组的时候,通过任何地址也就是Array_a输出都会得到改变的那个。

    转载请注明原文地址: https://ju.6miu.com/read-6676.html

    最新回复(0)