開闢的堆內存或者造成的上下文(進棧執行=>棧內存)是越多越好,仍是越少越好?javascript
函數執行就會造成棧內存(從內存中分配的一塊空間),若是內存都不銷燬釋放,很容易就會致使棧內存溢出(內存爆滿,電腦就卡死了), => 因此JS中一個重要的性能優化點:減小內存的使用java
- =>釋放堆內存
- =>釋放棧內存(也就是讓進棧執行的上下文,儘量出棧釋放)
瀏覽器有自動回收垃圾的機制,按期間隔某段時間,把全部沒有被佔用的內存回收釋放(這種垃圾回收機制,比其它語言要完善一些)web
若是堆內存用完後,咱們想去手動釋放它,則取消全部的佔用:賦值爲NULL(NULL是空對象指針,也就是不指向任何的堆內存)瀏覽器
//=>建立一個引用類型值,就會產生一個堆內存
//若是當前建立的堆內存不被其它東西所佔用了(瀏覽器會在空閒的時候,查找每個內存的引用情況,不被佔用的都會給回收釋放掉),則會釋放
let obj = {
name : 'xiaozhima'
};
let oop = obj;
//此時obj和oop都佔用着對象的堆內存,想要釋放堆內存,須要手動解除變量和值的關聯(null:空對象指針)
obj = null;
oop = null;
複製代碼
棧內存:性能優化
- 打開瀏覽器造成的全局做用域是棧內存
- 手動執行函數造成的私有做用域是棧內存
- 基於ES6中的let/const造成的塊做用域也是棧內存
- ......
棧內存銷燬:bash
- 全局棧內存:關掉頁面的時候纔會銷燬
- 私有棧內存:
- 1.通常狀況下,函數只要執行完成,造成的私有棧內存就會被銷燬釋放掉(排除出現無限極遞歸、出現死循環的模式)
- 2.可是一旦棧內存中的某個東西(通常都是堆地址)被私有做用域之外的事物給佔用了,則當前私有棧內存不能當即被釋放銷燬(特色:私有做用域中的私有變量等信息也保留下來了=>這種函數執行造成不能被釋放的私有棧內存,也叫作閉包)
function fn(){
//...
}
fn(); //=>函數執行造成棧內存,執行完成棧內存銷燬
function X(){
return function(){
//...
}
}
let f=X(); //=>f佔用了X執行造成的棧內存中的一個東西(返回小函數對應的堆),則X執行造成的棧內存不能被釋放了
複製代碼
當前內存被其它東西引用了,則給堆計數1(累加計數),取消佔用後,則減1,當減到零以後,瀏覽器就能夠把它釋放了閉包
var i = 5;
function fn(i) {
return function (n) {
console.log(n + (++i));
}
}
var f = fn(1);
f(2);
fn(3)(4);
fn(5)(6);
f(7);
console.log(i);
複製代碼
let x = 5;
function fn(x) {
return function(y) {
console.log(y + (++x));
}
}
let f = fn(6);
f(7);
fn(8)(9);
f(10);
console.log(x);
複製代碼
let a=0,
b=0;
function A(a){
A=function(b){
alert(a+b++);
};
alert(a++);
}
A(1);
A(2);
複製代碼
var n=0;
function a(){
var n=10;
function b(){
n++;
console.log(n);
}
b();
return b;
}
var c=a();
c();
console.log(n);
複製代碼
var test = (function(i){
return function(){
alert(i*=2);
}
})(2);
test(5);
複製代碼