zoukankan      html  css  js  c++  java
  • 学习 JavaScript (七) 内存问题

    内存问题是 JavaScript 比较底层的东西,依葫芦画瓢学会了怎么使用变量,但是对于内存的概念依然模糊,今天让我们一起来了解一下内存在这门语言是怎么样的存在。

    内存在不同类型的数值面前表现有很大的不同。我们把值赋给一个变量,解析器必须确定这个值是什么类型,先来了解变量的两个类型:

    • 基本类型:简单的数据段:Undefined、Null、Boolean、Number、String,按值访问,可以直接操作实际的值。

    • 引用类型:保存在内存中的对象:Object、Array。。JavaScript 赋值保存着对象的某个变量时,操作的是对象的引用;在为对象添加属性的时候,操作的是实际的对象。

    复制基本类型的数据时,计算机会重新分配一个位置给新的变量;但是复制引用类型的数据,计算机只是复制了一个指针,指向原有的对象。所以改变其中一个引用类型数据的属性时,访问另一个引用类型数据的属性能得到一样的结果,比如:

    复制基本类型并改变其中一个变量:

    let a = 20;
    let b = a;
    b = 30;
    console.log(a) // 20
    

    基础类型数据.jpg

    复制引用类型并改变其中一个变量的属性:

    let m = {a:10, b:20};
    let n = m;
    n.a = 15;
    console.log(m.a) // 15
    

    引用类型数据.jpg

    m,n 都指向一个引用类型的对象,所以改变 n 的属性会导致 m 的属性改变。上面表示的是变量之间基本的复制,但是注意:** 在所有函数的参数传递中,都是按值传递的,不是按照引用传递的 **。比如:

    function setName(obj){
       obj.name = "Nicholas";
       obj = new Object();
       obj.name = "Greg";
    }
    
    let person = new Object();
    setName(person);
    alert(person.name); // "Nicholas"
    

    JS 内存空间分为栈(stack)、堆(heap)、池(一般也会归类为栈中)。其中「栈」存放基本类型变量,遵循后进先出的原则;「堆」存放引用类型,堆存取数据的方式,则与书架与书非常相似,知道名字就能取出来用;池存放常量。

    检测一个变量是不是基本类型,用 typeof 操作符就可以搞定,但是这个操作符在遇到对象或者 null 时,返回 Object,我们不知道具体的类型。这时候,用 instanceof 来确认是什么类型的对象。

    内存泄漏与回收

    不再用到的内存,没有及时释放,就叫做内存泄露。

    大多数语言提供自动内存管理,减轻程序员的负担,这被称为“垃圾回收机制”(garbage collector)。原理很简单:找出那些不再继续使用的变量,然后释放其占用的内存。

    JavaScript 具有自动垃圾收集机制,不用程序员操太多心。而不同的浏览器可能会采取不同的回收策略,现代浏览器最常用的方式是标记清除,其次是引用计数。

    • 标记清除。垃圾收集器会给内存中的所有变量都添加标记,然后清除一些还会被使用的标记,即凡是环境中还会用到的变量,被其他变量引用的变量。还有标记的变量就会被垃圾收集器删除,完成内存的清除工作。
    • 引用计数。原理也很简单,跟踪每个变量被引用的次数。这里会产生一个棘手的问题,就是遇到 “循环引用” 就没招了。解决的方法是不再使用的对象,我们把它设置成空对象 Null 。看下面的例子:
    function(){
        let a = new Object();
        let b = new Object();
        
        a.oneObject = b;
        b.anotherObject = a;
    }
    
    

    上面的代码中,a 和 b 通过各自的属性实现相互引用,两者的被引用次数都是 2 。如果采用标记清楚策略,由于函数执行结束,这两个对象都离开了作用域,都会被清除。但是,采用引用计数策略,a 和 b 都还继续存在,因为他们的引用次数永远不会是 0。此时,只有手动断开引用。

    function(){
        let a = new Object();
        let b = new Object();
        
        a.oneObject = b;
        b.anotherObject = a;
        
        // 消除循环:
        a.oneObject = null
        b.anotherObject = null;
    }
    
    
  • 相关阅读:
    1094. Car Pooling
    121. Best Time to Buy and Sell Stock
    58. Length of Last Word
    510. Inorder Successor in BST II
    198. House Robber
    57. Insert Interval
    15. 3Sum java solutions
    79. Word Search java solutions
    80. Remove Duplicates from Sorted Array II java solutions
    34. Search for a Range java solutions
  • 原文地址:https://www.cnblogs.com/kurryluo/p/10050920.html
Copyright © 2011-2022 走看看