การแนะนำ
ภาษาระดับต่ำเช่น C มีการจัดการหน่วยความจำระดับต่ำเช่น malloc () และฟรี () ในทางกลับกันหน่วยความจำของ JavaScript นั้นได้รับการจัดสรรเมื่อตัวแปร (วัตถุ, สตริง ฯลฯ ) ถูกสร้างขึ้นจากนั้น "โดยอัตโนมัติ" จะเป็นอิสระเมื่อไม่ได้ใช้งานอีกต่อไป หลังนี้เรียกว่าคอลเล็กชั่นขยะ "อัตโนมัติ" นี้ทำให้งงงวยและให้จาวาสคริปต์ (และภาษาระดับสูงอื่น ๆ ) นักพัฒนาภาพลวงตา: พวกเขาสามารถเพิกเฉยต่อการจัดการหน่วยความจำ
วงจรชีวิตของหน่วยความจำ
ไม่ว่าภาษาการเขียนโปรแกรมจะเป็นอย่างไรวงจรชีวิตของหน่วยความจำก็เหมือนกัน:
1. จัดสรรหน่วยความจำที่คุณต้องการ
2. ใช้มัน (อ่านเขียน)
3. ปล่อย PS: และ "ใส่ช้างในตู้เย็น" หมายถึงเหมือนกัน
ส่วนแรกและส่วนที่สองของกระบวนการมีความชัดเจนในทุกภาษา ขั้นตอนสุดท้ายนั้นชัดเจนในภาษาระดับต่ำ แต่ในภาษาระดับสูงเช่น JavaScript ขั้นตอนสุดท้ายไม่ชัดเจน
การจัดสรรหน่วยความจำสำหรับ JavaScript
การเริ่มต้นตัวแปร
เพื่อที่จะไม่รบกวนโปรแกรมเมอร์ที่มีปัญหาในการจัดสรร JavaScript เสร็จสิ้นการจัดสรรหน่วยความจำเมื่อกำหนดตัวแปร
การคัดลอกรหัสมีดังนี้:
var n = 123;
var s = "azerty";
var o = {
A: 1,
B: NULL
}; // จัดสรรหน่วยความจำสำหรับวัตถุและตัวแปรที่มีอยู่
var a = [1, null, "bra"];
ฟังก์ชั่น f (a) {
ส่งคืน + 2;
} // จัดสรรหน่วยความจำสำหรับฟังก์ชั่น (วัตถุเรียกได้)
// นิพจน์ฟังก์ชั่นสามารถกำหนดวัตถุได้
someElement.addeventListener ('คลิก', function () {
onelement.style.backgroundColor = 'Blue';
}, เท็จ);
การจัดสรรหน่วยความจำผ่านการเรียกใช้ฟังก์ชัน
การเรียกใช้ฟังก์ชันบางอย่างส่งผลให้เกิดการจัดสรรหน่วยความจำวัตถุ:
การคัดลอกรหัสมีดังนี้:
var d = วันที่ใหม่ ();
var e = document.createelement ('div');
บางวิธีกำหนดตัวแปรใหม่หรือวัตถุใหม่:
การคัดลอกรหัสมีดังนี้:
var s = "azerty";
var s2 = s.substr (0, 3);
// เนื่องจากสตริงเป็นค่าคงที่ JavaScript อาจไม่จัดสรรหน่วยความจำ แต่มันจะเก็บเฉพาะช่วง 0-3
var a = ["ouais ouais", "nan nan"];
var a2 = ["Generation", "Nan Nan"];
var a3 = a.concat (a2); // มีสี่องค์ประกอบในอาร์เรย์ใหม่ที่เข้าร่วมอาร์เรย์ A และอาร์เรย์ A2
การใช้ค่า
กระบวนการใช้ค่าเป็นจริงการดำเนินการอ่านและเขียนของการจัดสรรหน่วยความจำซึ่งหมายความว่าตัวแปรหรือค่าคุณสมบัติของวัตถุสามารถเขียนได้หรือแม้แต่พารามิเตอร์ของฟังก์ชั่นสามารถส่งผ่านได้
เป็นอิสระเมื่อไม่จำเป็นต้องมีหน่วยความจำอีกต่อไป
ปัญหาการจัดการหน่วยความจำส่วนใหญ่อยู่ในขั้นตอนนี้ งานที่ยากที่สุดที่นี่คือการค้นหา "หน่วยความจำที่จัดสรรไม่จำเป็นต้องใช้อีกต่อไป" มักจะต้องมีนักพัฒนาในการพิจารณาว่าชิ้นส่วนของหน่วยความจำในโปรแกรมไม่จำเป็นต้องใช้และฟรีอีกต่อไป
ล่ามภาษาระดับสูงถูกฝังอยู่ใน "ตัวเก็บขยะ" และงานหลักของมันคือการติดตามการจัดสรรและการใช้หน่วยความจำเพื่อให้มันจะถูกปล่อยออกมาโดยอัตโนมัติเมื่อหน่วยความจำที่จัดสรรไม่ได้ใช้งานอีกต่อไป กระบวนการนี้เป็นการประมาณเนื่องจากเป็นไปไม่ได้ที่จะพิจารณาว่าจำเป็นต้องกำหนดหน่วยความจำบางชิ้นหรือไม่ (อัลกอริทึมบางอย่างไม่สามารถแก้ไขได้)
การรีไซเคิลขยะ
ดังที่ได้กล่าวไว้ข้างต้นคำถามของการมองหาโดยอัตโนมัติว่าหน่วยความจำบางอย่าง "ไม่ต้องการ" เป็นไปไม่ได้ที่จะพิจารณาหรือไม่ ดังนั้นการดำเนินการรวบรวมขยะสามารถแก้ปัญหาทั่วไปได้โดยมีข้อ จำกัด เท่านั้น ส่วนนี้จะอธิบายแนวคิดที่จำเป็นเพื่อทำความเข้าใจอัลกอริทึมการรวบรวมขยะหลักและข้อ จำกัด ของพวกเขา
อ้าง
อัลกอริทึมการรวบรวมขยะส่วนใหญ่ขึ้นอยู่กับแนวคิดของการอ้างอิง ในสภาพแวดล้อมที่มีการจัดการหน่วยความจำหากวัตถุได้รับอนุญาตให้เข้าถึงวัตถุอื่น (โดยปริยายหรือโดยชัดแจ้ง) จะเรียกว่าวัตถุที่อ้างถึงวัตถุอื่น ตัวอย่างเช่นวัตถุ JavaScript มีการอ้างอิงถึงต้นแบบ (การอ้างอิงโดยนัย) และการอ้างอิงถึงคุณสมบัติของมัน (การอ้างอิงที่ชัดเจน)
ที่นี่แนวคิดของ "วัตถุ" ไม่เพียง แต่วัตถุจาวาสคริปต์พิเศษเท่านั้น แต่ยังรวมถึงขอบเขตฟังก์ชัน (หรือขอบเขตคำศัพท์ทั่วโลก)
คอลเลกชันนับจำนวนอ้างอิง
นี่คืออัลกอริทึมการรวบรวมขยะที่ง่ายที่สุด อัลกอริทึมนี้ทำให้ง่ายขึ้น "ไม่ว่าวัตถุจะไม่จำเป็น" เป็น "วัตถุนั้นมีวัตถุอื่นที่อ้างถึง" หรือไม่ " หากไม่มีจุดอ้างอิงไปยังวัตถุ (ศูนย์อ้างอิง) วัตถุจะถูกนำกลับมาใช้ใหม่โดยกลไกการรวบรวมขยะ
ตัวอย่างเช่น
การคัดลอกรหัสมีดังนี้:
var o = {
A: {
B: 2
-
-
// สองวัตถุถูกสร้าง
// เห็นได้ชัดว่าไม่มีใครสามารถรวบรวมได้โดยขยะ
var o2 = o;
o = 1;
var OA = O2.A;
// ตอนนี้มีการอ้างอิงสองรายการเกี่ยวกับ "วัตถุนี้" หนึ่งคือ O2 และอีกอันคือ OA
O2 = "yo";
// เขาสามารถรีไซเคิลได้
// อย่างไรก็ตามวัตถุของคุณสมบัติ A ยังคงอ้างอิงโดย OA ดังนั้นจึงยังไม่สามารถรีไซเคิลได้
OA = null;
// สามารถเก็บขยะได้
ข้อ จำกัด : การอ้างอิงรีไซเคิล
อัลกอริทึมที่เรียบง่ายนี้มีข้อ จำกัด ว่าหากวัตถุอ้างถึงอีกวัตถุหนึ่ง (สร้างการอ้างอิงแบบวงกลม) พวกเขาอาจ "ไม่ต้องการมันอีกต่อไป" แต่พวกเขาจะไม่ถูกรีไซเคิล
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น f () {
var o = {};
var o2 = {};
OA = O2;
o2.a = o;
กลับ "azerty";
-
f ();
// สองวัตถุถูกสร้างและอ้างอิงซึ่งกันและกันสร้างลูป
// พวกเขาจะไม่ทิ้งขอบเขตของฟังก์ชั่นหลังจากถูกเรียก
// ดังนั้นพวกเขาจึงไร้ประโยชน์และสามารถรีไซเคิลได้
// อย่างไรก็ตามอัลกอริทึมการนับการอ้างอิงคำนึงถึงว่าพวกเขามีการอ้างอิงซึ่งกันและกันอย่างน้อยหนึ่งครั้งดังนั้นพวกเขาจะไม่ถูกนำกลับมาใช้ใหม่
ตัวอย่างที่เป็นประโยชน์
เช่น 6, 7 การรีไซเคิลการนับการอ้างอิงบนวัตถุ DOM ปัญหาที่พบบ่อยสำหรับพวกเขาคือการรั่วไหลของหน่วยความจำ:
การคัดลอกรหัสมีดังนี้:
var div = document.createElement ("div");
div.onclick = function () {
Dosomething ();
-
// div มีการอ้างอิงชี้ไปที่คุณสมบัติการประมวลผลเหตุการณ์ onclick
// การจัดการเหตุการณ์ยังมีการอ้างอิงถึง div ที่สามารถเข้าถึงได้ในขอบเขตฟังก์ชัน
// การอ้างอิงแบบวงกลมนี้จะทำให้ทั้งสองวัตถุถูกเก็บรวบรวม
อัลกอริทึมการล้างมาร์ค
อัลกอริทึมนี้ช่วยลดความซับซ้อน "ไม่ว่าวัตถุนั้นจะไม่จำเป็นอีกต่อไป" เป็น "ไม่ว่าจะเป็นวัตถุ"
อัลกอริทึมนี้ถือว่าการตั้งค่าวัตถุที่เรียกว่ารูท (ในจาวาสคริปต์รูทเป็นวัตถุทั่วโลก) อย่างสม่ำเสมอตัวเก็บขยะจะเริ่มต้นที่รูทค้นหาวัตถุทั้งหมดที่อ้างอิงจากรูทจากนั้นค้นหาวัตถุที่อ้างอิงโดยวัตถุเหล่านี้ ... เริ่มต้นจากรูทตัวเก็บขยะจะพบวัตถุทั้งหมดที่สามารถรับได้และวัตถุทั้งหมดที่ไม่สามารถรับได้
อัลกอริทึมนี้ดีกว่าภาษาก่อนหน้านี้เพราะ "วัตถุที่มีการอ้างอิงเป็นศูนย์" ไม่สามารถใช้งานได้เสมอ แต่ในทางกลับกันมันไม่จำเป็นต้องเป็นจริงอ้างถึง "การอ้างอิงแบบวงกลม"
ตั้งแต่ปี 2012 เบราว์เซอร์ที่ทันสมัยทั้งหมดได้ใช้อัลกอริทึมการรวบรวมขยะแท็กทำความสะอาด การปรับปรุงทั้งหมดของอัลกอริทึมการรวบรวมขยะ JavaScript จะขึ้นอยู่กับการปรับปรุงอัลกอริทึมการทำความสะอาดแท็กโดยไม่ต้องปรับปรุงอัลกอริทึมการทำความสะอาดแท็กเองและคำจำกัดความที่ง่ายขึ้นว่าวัตถุนั้นไม่จำเป็นอีกต่อไปหรือไม่
การอ้างอิงแบบวงกลมไม่ใช่ปัญหาอีกต่อไป
ในตัวอย่างด้านบนหลังจากการเรียกใช้ฟังก์ชันส่งคืนวัตถุทั้งสองไม่สามารถดึงได้จากวัตถุส่วนกลาง ดังนั้นพวกเขาจะถูกนำไปรีไซเคิลโดยนักสะสมขยะ
ตัวอย่างที่สองเช่นกันเมื่อ DIV และการประมวลผลเหตุการณ์ไม่สามารถเรียกคืนได้จากรูทพวกเขาจะถูกนำกลับมาใช้ใหม่โดยนักสะสมขยะ
ข้อ จำกัด : วัตถุต้องไม่สามารถใช้งานได้อย่างชัดเจน
แม้ว่านี่จะเป็นข้อ จำกัด แต่ก็ไม่ค่อยเกิดขึ้นซึ่งเป็นเหตุผลว่าทำไมในความเป็นจริง แต่มีเพียงไม่กี่คนที่ใส่ใจเกี่ยวกับกลไกการรวบรวมขยะ