javascript中內存的理解

javascript中內存的理解

js中的數據類型分爲基本數據類型和引用數據類型,即原始值和引用值,基本數據類型包括number、string、boolean、null、undefined;引用數據類型包括Object、Function、Array等

基本數據類型的變量名和變量值在內存中位置都爲棧,是存儲在棧中的簡單數據類型;引用數據類型變量名存儲在內存的棧中,變量值存儲在堆中。對於引用數據類型,變量名只是存儲在棧中的一個指針

  • 棧:數據類型的大小和生存期固定,佔用內存空間小,存取數度快,僅次於寄存器,主要存儲基本數據類型
  • 堆:數據類型的大小和生存期不固定,佔用內存空間大,存取數度慢,主要存儲引用數據類型

如下代碼

var num = 10;
var str = "hello";
var flag = true;
var obj = new Object();
var arr = ["a","b","c"];
var person = new Person(100,"zyb",25)
function Person(id,name,age){
    this.id = id;
    this.name = name;
    this.age = age
}

以上代碼在內存中的位置分析圖,如下棧中的obj指向堆中的Object,person指向第三部分,array指向第二部分javascript

內存
num:10
str:"hello"
flag:true
obj
person
array
Object
length:3
0:'a'
1:'b'
2:'c'
id:100
name:"zyb"
age:25
[[prototype]]
...

javascript有本身的垃圾回收機制,js解釋器會自動分配和回收內存;

  • 須要的時候分類配內存
  • 對內存讀寫操做
  • 不須要的時候釋放內存

如下是分配內存空間的幾種狀況:java

  • 變量初始化
  • 函數調用

何時釋放內存?

原理上一塊內存不須要了,就會被釋放掉,可是怎麼肯定一塊內存不須要?一個對象不被引用就會被釋放,一個對象被引用一次,引用計數就加1;算法

var outerObj = {//外層對象
    innerObj:{//內層對象
        msg:"hello"
    }
}
//內層對象被外層對象引用,外層對象被outerObj引用
//內層對象引用計數:1
//外層對象引用計數:1
//內層對象和外層對象不會被垃圾回收

var tempObj = outerObj
//內層對象引用計數:1
//外層對象引用計數:2
//內層對象和外層對象不會被垃圾回收

var outerObj = 1
//內層對象引用計數:1
//外層對象引用計數:1
//內層對象和外層對象不會被垃圾回收

var _tempObj = tempObj.innerObj
//內層對象引用計數:2
//外層對象引用計數:1
//內層對象和外層對象不會被垃圾回收

var tempObj = 2
//內層對象引用計數:1
//外層對象引用計數:0
//內層對象不會被垃圾回收
//外層對象會被垃圾回收

var _tempObj = 3
//內層對象引用計數:0
//外層對象引用計數:0
//內層對象會被垃圾回收
//外層對象會被垃圾回收

引用計數缺點:

function f(){
    var o = {};
    var o2 = {};
    o.a = o2; // o 引用 o2
    o2.a = o; // o2 引用 o

    return 「ok」;
}

f();

分析:函數

上面f函數執行完後,裏面的變量按理來講都會被釋放,可是o和o2互相調用,兩者的引用計數都不爲0,所以兩者都不會被收回,從而致使內存泄漏this

標記清除算法

當一個對象不可達的時候,這個對象就會被釋放,上面o和o2不被任何對象引用,即處於「不可達」狀態,能夠被回收prototype

函數傳遞參數,按值傳遞

function box(num){   //按值傳遞
    num+=10;
    return num;
}

var num = 10;
var result = box(num);
console.log(result); //20
console.log(num); //10

執行環境及做用域

var name ="zhangsan";

function setName(){
    name = "lisi"
}
setName();
console.log(name)//lisi

經過傳參

var name ="zhangsan";

function setName(name){
    console.log(name)//lisi
}
setName("lisi");
console.log(name)//zhangsan
相關文章
相關標籤/搜索