è¨æ¶é«ç®¡ç
ä»ç´¹
å C èªè¨ä¸æ¨£ä½éçèªè¨ï¼é½æèå¦ malloc() è· free() çä½éå½å¼è¨æ¶é«æ§ç®¡æ¬éãå¦ä¸æ¹é¢ï¼ç¶ JavaScript 建ç«äºç©(å¦ç©ä»¶ãå串ç)ææåé 空é給å¼ä¸èªåéæ¾ä¸å使ç¨çå¼ãå¾è çæµç¨ç¨±ä½çºåæ¶æ©å¶ãéåèªååçåæ¶æµç¨æ¯ä¸åæ··äºçæ ¹æºï¼å®æä½¿ JavaScript çéç¼è (æè å ¶ä»é«éèªè¨çéç¼è ) ç¢çå¯ä»¥ä¸é çæãè¨æ¶é«ç®¡çãçé¯èª¤èªç¥ã
è¨æ¶é«çå½é±æ
ä¸è«æ¯åªç¨®ç¨å¼èªè¨ï¼è¨æ¶é«çå½é±æ(é使¹å¼)å¹¾ä¹ç¸½æ¯ä¸æ¨£ï¼
- é ç½®ä½ ç¨å¼éè¦çè¨æ¶é«ç©ºé
- 使ç¨é ç½®å°çè¨æ¶é«ç©ºé(è®ï¼å¯«)
- ç¶ä¸åä½¿ç¨æéæ¾å·²è¢«é ç½®çè¨æ¶é«ç©ºé
卿æèªè¨ä¸ï¼ç¬¬äºé»ç(é使¹å¼)æ¯ç¢ºå®çã第ä¸é»ä»¥åæå¾ä¸é»å¨ä½éèªè¨ä¸æ¯ç¢ºå®çï¼ä½æ¯å¨é«éèªè¨å¦ JavaScript åé常æ¯ä¸æç¢ºçã
JavaScript çè¨æ¶é«é ç½®
å¼çåå§å
çºäºä¸è®éç¼è å°é ç½®æå°å°æ¾ï¼JavaScript æå¨å®£åå¼çåæå®æè¨æ¶é«é ç½®
var n = 123; // é
ç½®ä¸è¨æ¶é«ç©ºé給æ¸å
var s = "azerty"; // é
ç½®è¨æ¶é«ç©ºé給å串
var o = {
a: 1,
b: null,
}; //é
ç½®è¨æ¶é«ç©ºé給å
§å«å¼çç©ä»¶
// (åç©ä»¶ä¸æ¨£) åé
è¨æ¶é«çµ¦ä¸åé£å
// 該é£åå
å«ä¸äºå¼
var a = [1, null, "abra"];
function f(a) {
return a + 2;
} // åé
è¨æ¶é«çµ¦ä¸åå½å¼ (ä¸åå¯å¼å«çç©ä»¶)
// function expressions also allocate an object
someElement.addEventListener(
"click",
function () {
someElement.style.backgroundColor = "blue";
},
false,
);
èç±å½å¼å¼å«ä¾é ç½®
æäºå½å¼å¼å«å¾ç¢çç©ä»¶é ç½®ã
var d = new Date(); // é
ç½®ä¸åæ¥æç©ä»¶
var e = document.createElement("div"); // é
ç½®ä¸å DOM ç©ä»¶
æäºæ¹æ³é ç½®æ°ç弿ç©ä»¶ï¼
var s = "azerty";
var s2 = s.substr(0, 3); // s2 æ¯ä¸åæ°å串
// å çºå串æ¯ä¸ç¨®ä¸å¯è®çå¼ï¼
// JavaScript ææ±ºå®ä¸åé
æ°çè¨æ¶é«ï¼
// åªå²å 0 å° 3 éåç¯åçåå
ã
var a = ["ouais ouais", "nan nan"];
var a2 = ["generation", "nan nan"];
var a3 = a.concat(a2);
// ä¸åæååå
ç´ çæ°é£å
// å° a è a2 çå
ç´ ä¸²è¯èµ·ä¾
å¼ç使ç¨
åºæ¬ä¸ä½¿ç¨å¼è¡¨ç¤ºå°å·²è¢«é ç½®çè¨æ¶é«åè®å¯«ãå¯èç±è®åæå¯«å ¥è®æ¸ç弿ä¸åç©ä»¶ç¹æ§æçè³å³ä¸å忏å°å½æ¸ä¸ä¾å®ææ¤äºã
éæ¾ä¸å使ç¨çè¨æ¶é«
ç¶æåè«è«å°è¨æ¶é«ç®¡çï¼åé¡é常åºç¾å¨éåéæ®µãæå°é£ç工使¯å°æ¾ãå·²ä¸å被使ç¨çè¨æ¶é«é 置空éãã
ä½éèªè¨éè¦éç¼è èªå·±æ±ºå®ï¼ç¶ç¨åºå·è¡éæåå°æ¹æï¼æ¯å¦æå·²è¢«åé çè¨æ¶é«ä¸åéè¦ã並æåå°å ¶éæ¾ã
é«éçèªè¨ (e.g. JavaScript) æä¸åå«ä½åå¾åæ¶å¨(garbage collector) ç系統ï¼ä»ç工使¯è¿½è¹¤è¨æ¶é«åé çä½¿ç¨æ æ³ï¼ä»¥ä¾¿èªåéæ¾ä¸äºä¸å使ç¨çè¨æ¶é«ç©ºéãä½éååå¾åæ¶å¨åªæ¯ãåéãåå°èªåéæ¾è¨æ¶é«ç©ºéï¼å çºå¤æ·è¨æ¶é«ç©ºéæ¯å¦è¦ç¹¼çºä½¿ç¨ï¼éä»¶äºæ¯ãä¸å¯å¤å®(undecidable)ãçï¼ä¸è½ç¨æ¼ç®æ³ä¾è§£æ±ºï¼ã
åæ¶æ©å¶
å¦ä¸æè¿°ï¼è¦èªåå¤å®è¨æ¶é«ç©ºéãä¸å使ç¨ãæ¯ä¸å¯è½çãå æ¤ï¼åæ¶æ©å¶åªæ¯å¯¦ä½ä¸å大é¨ä»½ç¹å®æ æ³ä¸ç解決辦æ³ãæ¬ç« ç¯å°è§£é主è¦çåå¾åæ¶æ©å¶æ¼ç®æ³èä»åçéå¶ã
åè
åæ¶æ©å¶çæ¼ç®æ³ä¸»è¦æ¦å¿µæ¯åè(reference)æ¦å¿µãå¨è¨æ¶é«ç®¡ççä¸ä¸æä¸(context)ï¼å¦æä¸åç©ä»¶å¯ä»¥è¨ªåå°å¦ä¸åç©ä»¶(ç¡è«æ¯é±å¼æé¡¯å¼)ï¼å³ç¨±çºè©²ç©ä»¶åèå¦ä¸åç©ä»¶ãä¾å¦ï¼JavaScript çç©ä»¶é½æåè該ç©ä»¶çåå(prototype) (é±å¼åè) 以å該ç©ä»¶ç屬æ§å¼ (顯å¼åè)ã
å¨ååéçæ æ³ä¸ï¼ç©ä»¶çæ¦å¿µæ´å±å°æ¯æ®éç JavasScript ç©ä»¶æ´å»£ï¼éåæ¦å¿µéå å«å½æ¸ä½ç¨å (function scopes)ï¼æå ¨å±è©æ³ä½ç¨å (global lexical scope) ï¼ã
Reference-counting garbage collection
鿝ä¸åæå實çåå¾åæ¶æ¼ç®æ³ã éåæ¼ç®æ³å°åæ¬ãéåç©ä»¶åä¹ä¸æè¢«ä½¿ç¨ãç廣æ³å®ç¾©ç¸®æ¸å°ãæ²æå ¶ä»ä»»ä½ç©ä»¶åèå®ãã妿ä¸åç©ä»¶ä¸å¨è¢«ä»»ä½ç©ä»¶åèï¼å®å°è¢«è¦çºå¯åæ¶è¨æ¶é«çåå¾ã
ç¯ä¾
var o = {
a: {
b: 2,
},
};
// å
©åç©ä»¶è¢«åµé åºä¾ãå
¶ä¸ä¸åç©ä»¶(b)被è¦çºå¦ä¸åç©ä»¶(a)ç屬æ§ï¼ä¸¦ä¸è¢«è©²ç©ä»¶(a)åè
// å¦ä¸åç©ä»¶(a)被åé
給ä¸åè®æ¸(o)ï¼ä¸¦ä¸è¢«è®æ¸(o)åè
// 徿顝çï¼æ²æä»»ä½ç©ä»¶æè©²è¢«åæ¶
var o2 = o; // å¦å¤åµé 第äºåè®æ¸(o2)
// ä»åèä¸åç©ä»¶
o = 1; // ç¾å¨ï¼ç©ä»¶ o æå¦ä¸åä¸åçåè
// è忬å¨ç©ä»¶ o çç©ä»¶ï¼å被ç©ä»¶ o2 åè
var oa = o2.a; // è®æ¸ oa åèç©ä»¶ a
// ç©ä»¶ a æå
©åç©ä»¶åèå°å®ï¼ä¸åæ¯ o2ï¼ä¸¦ä¸å®æ¯ o2 ç屬æ§
// å¦ä¸åæ¯è®æ¸ oa
o2 = "yo"; // ç¾å¨ o2 è®æ 'yo'
// 忬æè©²æ²æä»»ä½ç©ä»¶åèå° a ï¼å æ¤å®æè©²è¢«åæ¶
// ä½ a ä»ç¶è¢«è®æ¸ oa åèï¼å æ¤å®ééè¢«åæ¶çå½é
oa = null; // ç¾å¨æ oa è®æ null
// å çºæ²æä»»ä½ç©ä»¶èè®æ¸åè a ï¼å æ¤ä»å¯ä»¥è¢«åæ¶
éå¶ï¼å¾ªç°
ç¶æ¶åå°å¾ªç°ææä¸åéå¶ãå¨ä¸é¢çä¾åä¸ï¼åµé å ©åç©ä»¶ä¸¦ç¸äºåèï¼å¾è製ä½ä¸å循ç°ãç¶å¼å«å½å¼æï¼ä»åæè©²è¶ åºä½ç¨ç¯åï¼å æ¤ä»å實é䏿¯ç¡ç¨ä¸å¯éæ¾ãä½åå¾åæ¶åèè¨æ¸æ¼ç®æ³æèªçºï¼å ©åç©ä»¶é½è³å°è¢«åè䏿¬¡ï¼å æ¤å ©å齿¯ä¸è½è¢«åæ¶çã
function f() {
var o = {};
var o2 = {};
o.a = o2; // o åè o2
o2.a = o; // o2 åè o
return "azerty";
}
f();
ç實æ¡ä¾
Internet Explorer 6 å 7 æä¸å DOM ç©ä»¶çåå¾åæ¶åèè¨æ¸ãå¾ªç°æ¯ä¸åé æè¨æ¶é«æ´©æ¼(memory leaks)ç常è¦åé¡ï¼
var div;
window.onload = function () {
div = document.getElementById("myDivElement");
div.circularReference = div;
div.lotsOfData = new Array(10000).join("*");
};
å¨ä¸é¢çä¾åä¸ï¼DOM å ç´ ãmyDivElementãå¨ãcircularReferenceã屬æ§ä¸æä¸å循ç°åèãå¦æè©²å±¬æ§æªè¢«ç´æ¥åªé¤æçºé¶ï¼åå¾åæ¶åèè¨æ¸å°è¦å ¶å§çµè³å°æä¸ååèä¿æä¸è®ï¼ä¸¦å° DOM å ç´ ä¿åå¨è¨æ¶é«è£¡ï¼å³ä½¿å®å·²å¾ DOM 樹ä¸ç§»é¤ãå¦æè©² DOM å ç´ ææå¤§éè³æï¼å¦åä¸é¢çä¾åä¸ç lotsOfData 屬æ§ï¼ï¼åæ¤è³ææä½ç¨çè¨æ¶é«å°æ°¸é 䏿鿾ã
æ¨è¨åæ¸ çæ¼ç®æ³
éåæ¼ç®æ³å°ãéåç©ä»¶åä¹ä¸æè¢«ä½¿ç¨ãçå®ç¾©ç¸®æ¸å°ãéåç©ä»¶ä¸å¯å°éãã
éåæ¼ç®æ³åè¨ä¸çµç©ä»¶ï¼å ¶åçºãæ ¹ (roots)ãï¼å¨ JavaScript ä¸ï¼æ ¹(roots)æ¯å ¨å±ç©ä»¶ï¼ãåå¾åæ¶å¨å®æå¾éäºæ ¹éå§ï¼å°è¨ªææè¢«æ ¹åèçç©ä»¶èé£äºç©ä»¶åèçç©ä»¶ãåå¾åæ¶å¨æåæ¶é£äºæ²æè¢«å°è¨ªçå°ç©ä»¶ã
éåæ¼ç®æ³æ¯åä¸åæ¼ç®æ³æ´å¥½ï¼å çºä¸åä¸è¢«ä»»ä½ç©ä»¶åèçç©ä»¶ï¼ä¸å®ç¡æ³å¾æ ¹è¢«å°è¨ªå°ãç¶èï¼ä¸åç¡æ³å¾æ ¹è¢«å°è¨ªå°çç©ä»¶ï¼ä¸ä¸å®ä¸è¢«ä»»ä½ç©ä»¶åèï¼å¯ä»¥å¨å¾ªç°çä¾åä¸ç¼ç¾éä»¶äºã
æªè³ 2012 å¹´ï¼ææç¾ä»£ç覽å¨é½ä½¿ç¨æ¨è¨åæ¸ ççåå¾åæ¶å¨ã å¨éå»ç幾年裡ï¼JavaScript åå¾åæ¶é åçæææ¹é²é½æ¯å°éåæ¼ç®æ³ç實ä½èæ¹é²ï¼ä½ä¸¦æªæ¹é²åå¾åæ¶æ¼ç®æ³æ¬èº«ï¼ä¹æ²æç¸®æ¸åå¾çå®ç¾© ãéåç©ä»¶åä¹ä¸æè¢«ä½¿ç¨ãã
循ç°ä¸åæ¯ä¸ååé¡
å¨ä¸é¢ç第ä¸åç¯ä¾ä¸ï¼å½å¼å¼å«è¿åå¾ï¼é£å ©åç©ä»¶ä¸åè¢«å ¨å±ç©ä»¶å¯ä»¥å°è¨ªå°çç©ä»¶åèã å æ¤ï¼å®åå°è¢«åå¾åæ¶å¨ç¼ç¾ï¼è¦çºä¸å¯éå°çã
第äºåç¯ä¾ä¹æ¯ä¸æ¨£çã 䏿¦ div åå®çèçç¨åºå¾æ ¹æ¬ä¸ç¡æ³å°è¨ªï¼å®åé½æè¢«åå¾åæ¶æï¼å管ä»åèªèº«ç¸äºåèã
éå¶ï¼ç©ä»¶å¿ é æé¡¯çä¸å¯éå°
éç¶æéåéå¶åå¨ï¼ä½å¨å¯¦åå»å¾å°ç¼çãé乿¯å¹¾ä¹æ²æäººéå¿éä»¶äºçåå ã
Node.js
Node.js offers additional options and tools for configuring and debugging memory issues that may not be available for JavaScript executed within a browser environment.
V8 Engine Flags
The max amount of available heap memory can be increased with a flag:
node --max-old-space-size=6000 index.js
We can also expose the garbage collector for debugging memory issues using a flag and the Chrome Debugger:
node --expose-gc --inspect index.js