栈内存or堆内存

今天做每日一练的时候遇到的知识点
题目:用JS写出一个对象obj,使得obj.obj.obj.obj===obj。也就是说,不管出现多少次.obj, 都得到obj

实现方法:使用了内存地址
var obj = {};
obj.obj = obj;
console.log(obj.obj.obj.obj===obj);

一、从变量入手
    Javascript中的变量分为基本类型和引用类型
    基本类型是保存在栈内存中的简单数据段,而引用类型指的是保存在堆内存的变量
二、基本类型
    基本类型有undefined, null, boolean, number, string, 这些类型在内存中分别战友固定大小的控件,他们的值保存在栈控件,是通过按值来访问的。
三、引用类型
    引用类型,值大小不固定,栈内存中存放的知识该对象的访问地址。当查询引用类型的变量时,先从栈中读取内存地址,然后再通过地址找到堆中的值,这种叫做按引用访问。

    我们经常会遇到的面试题
     var a = 20;
    var b = a;
    b = 30;
    //这时候a的值为20,因为使用的是栈内存,是按值来访问的。
    
    var m = {a:10, b:20};
    var n = m;
    n.a = 15;
    //这时候m.a的值为15,因为m和n是指向同一个对象的内存地址,n.a改变了指向堆内存的对象数据,因此,m.a也跟着改变
四、为什么会有栈内存和堆内存之分
    通常与垃圾回收机制有关,为了使程序运行时占用的内存最小。
    当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法对的内存栈也将自然销毁了。因此,所有在方法中定义的变量都是放在栈内存中的;
    当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,一遍反复利用(因为对象的创建成本比较大),这个运行时数据区就是堆内存。堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见),则这个对象依然不会被销毁,只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。
五、内存空间管理
    因为javascript具有自动垃圾收集机制,所以我们在开发时好像不用关心内存的使用问题,内存的分配与回收都完全实现了自动管理。了解内存机制有助于我们清晰的认识到自己写的代码在执行过程中发生过什么,从而写出性能更加优秀的代码。
    javascript的内存生命周期
    1. 分配你所需要的内存
    2.使用分配到的内存(读、写)
    3.不需要时将其释放、归还
    javascript有自动垃圾收集机制,那么这个自动垃圾收集机制会找到那些不再继续使用的值,然后释放其占用的内存,会每隔固定的时间段就执行一次释放操作。在Javascript中,最常用的是通过标记清除的算法来找到哪些对象时不再继续使用的,因此a=null其实仅仅只是做了一个释放引用的操作,让a原本对应的值失去引用,脱离执行环境,这个值会在下一次垃圾收集器执行操作时被找到并释放。
    在局部作用域中,当函数执行完毕,局部变量也就没有存在的必要了,因此垃圾收集器很容易做出判断并回收,但是全局变量什么时候需要自动释放内存则很难判断,因此在我们开发中,需要尽量避免使用全局变量,以确保性能问题。
六、回到每日一练这个问题
    因为obj是个对象,指向堆内存,这时obj.obj=obj也是上面那个对象,同一个堆内存,形成一个循环


猜你喜欢

转载自blog.csdn.net/qq_32439381/article/details/80111523