بالمقارنة مع C/C ++ ، فإن معالجة JavaScript في الذاكرة في JavaScript التي نستخدمها جعلتنا نولي المزيد من الاهتمام لكتابة منطق العمل في التطوير. ومع ذلك ، مع التعقيد المستمر للشركة ، فإن تطوير تطبيقات صفحة واحدة ، وتطبيقات HTML5 المتنقلة ، وبرامج Node.js ، وما إلى ذلك ، لم يعد تدفق الذاكرة الناجم عن مشاكل الذاكرة في JavaScript غير مألوفة.
ستناقش هذه المقالة استخدام الذاكرة وتحسينها من مستوى لغة JavaScript. من الجوانب التي يعرفها الجميع أو سماعها قليلاً ، إلى الأشياء التي لن يلاحظها الجميع معظم الوقت ، سنقوم بتحليلها واحدًا تلو الآخر.
1. إدارة الذاكرة على مستوى اللغة
1.1 النطاق
النطاق هو آلية تشغيل مهمة للغاية في برمجة JavaScript. إنه لا يجذب انتباه المبتدئين في برمجة JavaScript المتزامنة ، ولكن في البرمجة غير المتزامنة ، أصبحت مهارات التحكم في النطاق الجيد مهارة ضرورية لمطوري JavaScript. بالإضافة إلى ذلك ، يلعب النطاق دورًا مهمًا في إدارة ذاكرة JavaScript.
في JavaScript ، يمكن استدعاء الوظائف ، مع البيانات والنطاقات العالمية التي يمكن تحديدها.
كما هو موضح في الكود التالي كمثال:
نسخة الكود كما يلي:
var foo = function () {
var local = {} ؛
} ؛
foo () ؛
console.log (محلي) ؛ // => غير محدد
var bar = function () {
local = {} ؛
} ؛
حاجِز()؛
console.log (محلي) ؛ // => {}
هنا نحدد وظيفة foo () ودالة الشريط (). نيتهم هي تحديد متغير اسمه محلي. لكن النتيجة النهائية مختلفة تمامًا.
في وظيفة FOO () ، نستخدم عبارة VAR لإعلان أنه يتم تعريف متغير محلي. نظرًا لأن النطاق يتكون من جسم الوظيفة ، يتم تعريف هذا المتغير في النطاق. علاوة على ذلك ، لا توجد معالجة تمديد نطاق في وظيفة FOO () ، لذلك بعد تنفيذ الوظيفة ، يتم أيضًا تدمير المتغير المحلي. ومع ذلك ، لا يمكن الوصول إلى هذا المتغير في النطاق الخارجي.
في وظيفة الشريط () ، لا يتم الإعلان عن المتغير المحلي باستخدام عبارة VAR ، ولكن بدلاً من ذلك يعرّف مباشرة المحلية كمتغير عالمي. لذلك ، يمكن الوصول إلى هذا المتغير بواسطة النطاق الخارجي.
نسخة الكود كما يلي:
local = {} ؛
// التعريف هنا يعادل
global.local = {} ؛
1.2 سلسلة النطاق
في برمجة JavaScript ، ستواجه بالتأكيد سيناريوهات تعشش وظائف متعددة الطبقات ، وهي تمثيل نموذجي لسلاسل النطاق.
كما هو موضح في الكود التالي:
نسخة الكود كما يلي:
وظيفة foo () {
var val = 'hello' ؛
شريط الدالة () {
وظيفة baz () {
Global.val = 'World ؛'
}
baz () ؛
console.log (val) ؛ // => مرحبًا
}
حاجِز()؛
}
foo () ؛
استنادًا إلى التفسير السابق حول النطاق ، قد تعتقد أن النتيجة الموضحة في الكود هنا هي العالم ، ولكن النتيجة الفعلية هي مرحبًا. سيبدأ العديد من المبتدئين في الشعور بالارتباك هنا ، لذلك دعونا نلقي نظرة على كيفية عمل هذا الرمز.
منذ JavaScript ، يبدأ البحث عن معرفات متغيرة من النطاق الحالي وينظر إلى الخارج حتى النطاق العالمي. لذلك ، لا يمكن تنفيذ الوصول إلى المتغيرات في رمز JavaScript إلا في الخارج ، ولكن ليس في الاتجاه المعاكس.
يحدد تنفيذ دالة BAZ () VAL عالمي متغير في النطاق العالمي. في وظيفة الشريط () ، عند الوصول إلى المعرف Val ، فإن مبدأ البحث من الداخل إلى الخارج هو: إذا لم يتم العثور عليه في نطاق وظيفة الشريط ، فإنه يذهب إلى الطبقة السابقة ، أي نطاق وظيفة Foo ().
ومع ذلك ، فإن مفتاح إرباك الجميع هو: يجد الوصول إلى المعرف متغيرًا مطابقًا في نطاق وظيفة FOO () ، ولن يستمر في البحث إلى الخارج ، وبالتالي فإن المتغير العالمي المحدد في وظيفة BAZ () ليس له أي تأثير في هذا الوصول المتغير.
1.3 الإغلاق
نحن نعلم أن البحث معرف في JavaScript يتبع مبدأ الداخل إلى الخارج. ومع ذلك ، مع تعقيد منطق العمل ، فإن أمر تسليم واحد بعيد عن تلبية الاحتياجات الجديدة المتزايدة.
لنلقي نظرة على الكود التالي:
نسخة الكود كما يلي:
وظيفة foo () {
var local = 'hello' ؛
وظيفة الإرجاع () {
إرجاع محلي ؛
} ؛
}
var bar = foo () ؛
console.log (bar ()) ؛ // => مرحبًا
التكنولوجيا التي تسمح للنطاق الخارجي للوصول إلى النطاق الداخلي كما هو موضح هنا هي الإغلاق. بفضل تطبيق وظائف الترتيب العالي ، يكون نطاق وظيفة FOO () "ممتدًا".
تقوم دالة FOO () بإرجاع دالة مجهولة المصدر ، الموجودة في نطاق وظيفة FOO () ، بحيث يمكنك الوصول إلى المتغير المحلي في نطاق وظيفة FOO () وحفظ مرجعها. نظرًا لأن هذه الوظيفة تُرجع مباشرة المتغير المحلي ، يمكن تنفيذ وظيفة BAR () مباشرة في النطاق الخارجي للحصول على المتغير المحلي.
تعد عمليات الإغلاق ميزة عالية المستوى من JavaScript ، ويمكننا استخدامها لتحقيق المزيد من التأثيرات الأكثر تعقيدًا لتلبية الاحتياجات المختلفة. ومع ذلك ، تجدر الإشارة إلى أنه نظرًا لأن الوظيفة ذات المرجع المتغير الداخلي يتم إخراجها من الوظيفة ، فلن يتم تدمير المتغيرات في هذا النطاق بعد تنفيذ الوظيفة حتى يتم إلغاء جميع الإشارات إلى المتغيرات الداخلية. لذلك ، يمكن أن يتسبب تطبيق الإغلاق بسهولة في أن تكون الذاكرة غير مجدية.
2. آلية إعادة تدوير ذاكرة JavaScript
هنا سوف آخذ محرك V8 الذي يستخدمه Chrome و Node.js وأطلقه Google كمثال لتقديم آلية إعادة تدوير الذاكرة في JavaScript بإيجاز. لمزيد من المحتوى التفصيلي ، يمكنك شراء كتاب Friend Friend Park Ling الخاص بي "متعمق وسهل فهم Node.js" للتعلم ، وهي مقدمة مفصلة للغاية في الفصل "التحكم في الذاكرة".
في V8 ، يتم تخصيص جميع كائنات JavaScript من خلال "الكومة".
عندما نعلن وتعيين القيم في الكود ، سيقوم V8 بتخصيص جزء من هذا المتغير في ذاكرة الكومة. إذا كانت الذاكرة المطلوبة غير كافية لتخزين هذا المتغير ، فسيستمر V8 في التقدم بطلب للحصول على الذاكرة حتى يصل حجم الكومة إلى حد الذاكرة لـ V8. بشكل افتراضي ، يبلغ الحد الأعلى لذاكرة الكومة لـ V8 1464 ميغابايت على أنظمة 64 بت و 732 ميجابايت على أنظمة 32 بت ، والتي تبلغ حوالي 1.4 جيجابايت و 0.7 جيجابايت.
بالإضافة إلى ذلك ، يدير V8 كائنات JavaScript في ذاكرة الكومة في الأجيال: الجيل الجديد والجيل القديم. الجيل الجديد هو كائنات JavaScript ذات دورات البقاء القصيرة ، مثل المتغيرات المؤقتة ، والسلاسل ، إلخ ؛ في حين أن الجيل القديم هو كائنات ذات دورات بقاء طويلة بعد مجموعات القمامة المتعددة ، مثل وحدات التحكم الرئيسية ، وكائنات الخادم ، إلخ.
لطالما كانت خوارزميات إعادة تدوير القمامة جزءًا مهمًا من تطوير لغات البرمجة ، كما أن خوارزميات إعادة تدوير القمامة المستخدمة في V8 كما يلي:
1. خوارزمية الغطاء: يتم تنفيذ إدارة مساحة الذاكرة من خلال النسخ ، وتستخدم بشكل رئيسي في مساحة ذاكرة الجيل الجديد ؛
2. خوارزمية SWEX والخوارزمية الموقوتة: يتم فرز ذاكرة الكومة وإعادة تدويرها من خلال وضع العلامات ، وتستخدم بشكل رئيسي لفحص وإعادة تدوير كائنات الجيل القديم.
ملاحظة: يمكن تعلم تطبيقات مجموعة Garbage أكثر تفصيلاً من خلال قراءة الكتب والمستندات والرمز المصدر.
دعونا نلقي نظرة على الظروف التي سيعيدها محرك JavaScript لمحرك JavaScript.
2.1 النطاق والمرجع
غالبًا ما يعتقد المبتدئون عن طريق الخطأ أنه عند تنفيذ الوظيفة ، سيتم تدمير الكائن المعلن داخل الوظيفة. ولكن في الواقع ، هذا الفهم ليس صارمًا وشاملًا ، ومن السهل الخلط بينه.
المرجع هو آلية مهمة للغاية في برمجة JavaScript ، ولكن من الغريب أن معظم المطورين لن ينتبهوا إليها أو حتى فهمها. يشير المرجع إلى العلاقة التجريدية "وصول الكود إلى الكائنات". إنه يشبه إلى حد ما مؤشرات C/C ++ ، ولكن ليس نفس الشيء. المرجع هو أيضًا الآلية الأكثر أهمية لمحرك JavaScript في جمع القمامة.
الرمز التالي مثال:
نسخة الكود كما يلي:
// ......
var val = 'hello world' ؛
وظيفة foo () {
وظيفة الإرجاع () {
إرجاع فال
} ؛
}
global.bar = foo () ؛
// ......
بعد قراءة هذا الرمز ، هل يمكنك معرفة الكائنات التي لا تزال قائمة بعد تنفيذ هذا الجزء من الكود؟
وفقًا للمبادئ ذات الصلة ، فإن الكائنات التي لم يتم إعادة تدويرها وإصدارها في هذا الرمز تشمل Val و Bar (). ما الذي يجعلهم بالضبط غير قادرين على إعادة تدويره؟
كيف يقوم محرك JavaScript بجمع القمامة؟ يتم استخدام خوارزمية جمع القمامة المذكورة أعلاه فقط أثناء إعادة التدوير. فكيف تعرف الأشياء التي يمكن إعادة تدويرها وأي الكائنات تحتاج إلى الاستمرار في البقاء؟ الجواب هو إشارة إلى كائن JavaScript.
في رمز JavaScript ، حتى إذا قمت ببساطة بتدوين اسم متغير كخط واحد دون القيام بأي شيء ، فإن محرك JavaScript سيعتقد أن هذا سلوك الوصول إلى الكائن وهناك مرجع إلى الكائن. من أجل التأكد من أن سلوك جمع القمامة لا يؤثر على تشغيل منطق البرنامج ، يجب ألا يقوم محرك JavaScript بإعادة تدوير الكائنات المستخدمة ، وإلا فسيكون فوضويًا. لذلك ، فإن معيار الحكم على ما إذا كان الكائن قيد الاستخدام هو ما إذا كان لا يزال هناك إشارة إلى الكائن. ولكن في الواقع ، يعد هذا حل وسط ، لأنه يمكن نقل مراجع JavaScript ، لذلك قد يكون هناك بعض المراجع التي يتم إحضارها إلى النطاق العالمي ، ولكن في الواقع ، لم يعد من الضروري الوصول إليها في منطق العمل ويجب إعادة تدويرها ، لكن محرك JavaScript لا يزال يعتقد بشدة أن البرنامج لا يزال يحتاجه.
كيفية استخدام المتغيرات والمراجع في الموقف الصحيح هو المفتاح لتحسين جافا سكريبت من مستوى اللغة.
3. قم بتحسين JavaScript الخاص بك
وصلت أخيرًا إلى هذه النقطة. شكرا جزيلا لرؤية هذا مع الصبر. بعد العديد من المقدمات أعلاه ، أعتقد أن لديك فهمًا جيدًا لآلية إدارة ذاكرة JavaScript. ثم ستجعلك المهارات التالية تشعر بتحسن.
3.1 استفد من الوظائف بشكل جيد
إذا كان لديك عادة قراءة مشاريع JavaScript الممتازة ، فستجد أنه عند تطوير رمز JavaScript الأمامي ، يستخدم العديد من اللاعبين الكبار في كثير من الأحيان وظيفة مجهولة لللفها على الطبقة الخارجية من الكود.
نسخة الكود كما يلي:
(وظيفة() {
// رمز الأعمال الرئيسي
}) () ؛
البعض أكثر تقدمًا:
نسخة الكود كما يلي:
؛ (الوظيفة (الفوز ، المستند ، $ ، غير محدد) {
// رمز الأعمال الرئيسي
}) (نافذة ، مستند ، jQuery) ؛
حتى حلول التحميل المعيارية في الواجهة الأمامية مثل المتطلبات ، Seajs ، OZJs ، إلخ. تعتمد جميعها شكلًا مماثلًا:
نسخة الكود كما يلي:
// متطلبات
define (['jQuery'] ، function ($) {
// رمز الأعمال الرئيسي
}) ؛
// seajs
Define ('module' ، ['dep' ، 'Underscore'] ، function ($ ، _) {
// رمز الأعمال الرئيسي
}) ؛
إذا قلت أن العديد من رموز Node.js لا تتم معالجة مشاريع المصدر المفتوح بهذه الطريقة ، فأنت مخطئ. قبل تشغيل الكود فعليًا ، ستقوم Node.js بلف كل ملف .js في النموذج التالي:
نسخة الكود كما يلي:
(الوظيفة (الصادرات ، تتطلب ، الوحدة ، __dirname ، __filename) {
// رمز الأعمال الرئيسي
}) ؛
ما هي فوائد القيام بذلك؟ نعلم جميعًا أنه في بداية المقال ، قلنا أن JavaScript يمكن أن يكون لها وظائف محددة ، مع بيانات ونطاق عالمي. نعلم أيضًا أن الكائنات المحددة في النطاق العالمي قد تعيش حتى تخرج العملية. إذا كان كائنًا كبيرًا ، فسيكون ذلك مزعجًا. على سبيل المثال ، يحب بعض الأشخاص تقديم قوالب في JavaScript:
نسخة الكود كما يلي:
<؟ PHP
$ db = mysqli_connect (الخادم ، المستخدم ، كلمة المرور ، 'myapp') ؛
موضوعات $ = mysqli_query ($ dB ، "Select * from thispics ؛") ؛
؟>
<! doctype html>
<html lang = "en">
<head>
<meta charset = "utf-8">
<title> هل أنت رجل مضحك دعوة من القرود؟ </title>
</head>
<body>
<ul id = "موضوعات"> </ul>
<script type = "text/tmpl" id = "topic-tmpl">
<li>
<h1> <٪ = title ٪> </h1>
<p> <٪ = content ٪> </p>
</li>
</script>
<script type = "text/javaScript">
var data = <؟ php echo json_encode ($ thision) ؛ ؟> ؛
var topictmpl = document.queryselector ('#topic-tmpl'). innerhtml ؛
var render = function (tmlp ، view) {
var compiled = tmlp
.replace (// n/g ، '// n')
.replace (/<٪ = ([/s/s]+؟) ٪>/g ، وظيفة (مطابقة ، رمز) {
إرجاع " + Escape (' + code +') +" '؛
}) ؛
المترجمة = [
'var res = "" ؛' ،
"مع (عرض || {}) {'،
'res = "' ' + complive +'" ؛ '،
'}' ،
"عودة الدقة"
]. الانضمام ('/n') ؛
var fn = دالة جديدة ('view' ، reglized) ؛
إرجاع fn (عرض) ؛
} ؛
موضوعات var = document.queryselector ('#thispics') ؛
وظيفة init ()
data.foreach (وظيفة (موضوع) {
thispics.innerhtml += render (topictmpl ، topic) ؛
}) ؛
}
init () ؛
</script>
</body>
</html>
غالبًا ما يمكن رؤية هذا النوع من الكود في أعمال المبتدئين. ما هي المشاكل هنا؟ إذا كانت كمية البيانات التي تم الحصول عليها من قاعدة البيانات كبيرة جدًا ، فسيكون متغير البيانات في وضع الخمول بعد أن يكمل الواجهة الأمامية عرض القالب. ومع ذلك ، نظرًا لأن هذا المتغير محدد في النطاق العالمي ، فإن محرك JavaScript لن يعيد تدويره ويدمره. سيستمر هذا في الوجود في ذاكرة كومة الجيل القديم حتى يتم إغلاق الصفحة.
ولكن إذا قمت بإجراء بعض التعديلات البسيطة للغاية ولفت طبقة من الوظائف خارج الكود المنطقي ، فسيكون التأثير مختلفًا تمامًا. بعد اكتمال عرض واجهة المستخدم ، يتم أيضًا إلغاء إشارة الرمز إلى البيانات. عند تنفيذ الوظيفة الخارجية ، يبدأ محرك JavaScript في التحقق من الكائنات الموجودة فيه ، ويمكن إعادة تدوير البيانات.
3.2 لا تحدد أبدًا المتغيرات العالمية
لقد تحدثنا للتو عن ذلك عندما يتم تعريف متغير في النطاق العالمي ، فإن محرك JavaScript لن يعيد تدويره ويدمره بشكل افتراضي. سيستمر هذا في الوجود في ذاكرة كومة الجيل القديم حتى يتم إغلاق الصفحة.
ثم اتبعنا دائمًا مبدأ: لا نستخدم المتغيرات العالمية أبدًا. على الرغم من أن المتغيرات العالمية سهلة للغاية بالفعل ، إلا أن المشكلات الناجمة عن المتغيرات العالمية أكثر خطورة بكثير من الراحة التي تجلبها.
جعل المتغيرات أقل عرضة لإعادة تدويرها ؛
1. يمكن بسهولة حدوث ارتباك عندما يتعاون العديد من الأشخاص ؛
2. من السهل أن تتداخل في سلسلة النطاق.
3. بالتزامن مع وظيفة التفاف أعلاه ، يمكننا أيضًا التعامل مع "المتغيرات العالمية" من خلال وظائف التغليف.
3.3 متغيرات غير مرجعية يدويًا
إذا لم يكن هناك حاجة إلى متغير في رمز العمل ، فيمكن أن يتم إلغاء تدوين المتغير يدويًا لجعله معاد تدويره.
نسخة الكود كما يلي:
var data = { / * بعض البيانات الكبيرة * /} ؛
// بلاه بلاه بلاه
البيانات = فارغة ؛
3.4 استفد من عمليات الاسترجاعات بشكل جيد
بالإضافة إلى استخدام عمليات الإغلاق للوصول الداخلي المتغير ، يمكننا أيضًا استخدام وظيفة رد الاتصال الشهيرة الآن لمعالجة الأعمال.
نسخة الكود كما يلي:
وظيفة getData (رد الاتصال) {
var data = 'بعض البيانات الكبيرة' ؛
رد الاتصال (NULL ، البيانات) ؛
}
getData (وظيفة (err ، البيانات) {
console.log (البيانات) ؛
وظائف رد الاتصال هي تقنية لأسلوب تمرير الاستمرار (CPS). ينقل هذا النمط من البرمجة تركيز العمل للوظيفة من قيمة الإرجاع إلى وظيفة رد الاتصال. ولديه العديد من الفوائد على الإغلاق:
1. إذا كانت المعلمات التي تم تمريرها هي النوع الأساسي (مثل الأوتار ، والقيم الرقمية) ، فسيتم نسخ المعلمات الرسمية التي تم تمريرها في وظيفة رد الاتصال ، وسيكون من الأسهل إعادة تدويرها بعد استخدام رمز العمل ؛
2. من خلال عمليات الاسترجاعات ، بالإضافة إلى إكمال الطلبات المتزامنة ، يمكننا أيضًا استخدامها في البرمجة غير المتزامنة ، وهو أسلوب كتابة شائع جدًا الآن ؛
3. وظيفة رد الاتصال نفسها عادة ما تكون وظيفة مجهولة. بمجرد تنفيذ وظيفة الطلب ، سيتم إلغاء الإشارة إلى وظيفة رد الاتصال نفسها وسيتم إعادة تدويرها.
3.5 إدارة الإغلاق الجيدة
عندما يجب أن تستخدم احتياجات أعمالنا (مثل ربط الأحداث الدائرية ، والسمات الخاصة ، وعمليات الاسترجاعات بالحجج ، وما إلى ذلك) ، يجب أن تستخدم الإغلاق ، يرجى توخي الحذر في التفاصيل.
يمكن القول أن أحداث ربط الحلقة هي دورة إلزامية للبدء مع إغلاق JavaScript. لنفترض سيناريو: هناك ستة أزرار ، تقابل ستة أحداث. عندما ينقر المستخدم على الزر ، يتم إخراج الأحداث المقابلة في المكان المحدد.
نسخة الكود كما يلي:
var btns = document.queryselectorall ('. btn') ؛ // 6 عناصر
var output = document.queryselector ('#output') ؛
أحداث var = [1 ، 2 ، 3 ، 4 ، 5 ، 6] ؛
// الحالة 1
لـ (var i = 0 ؛ i <btns.length ؛ i ++) {
btns [i] .onclick = function (evt) {
output.innertext + = 'clicked' + events [i] ؛
} ؛
}
// الحالة 2
لـ (var i = 0 ؛ i <btns.length ؛ i ++) {
btns [i] .onclick = (function (index) {
وظيفة الإرجاع (evt) {
output.innertext + = 'clicked' + أحداث [index] ؛
} ؛
})(أنا)؛
}
// الحالة 3
لـ (var i = 0 ؛ i <btns.length ؛ i ++) {
btns [i] .onclick = (function (event) {
وظيفة الإرجاع (evt) {
output.innertext + = 'clicked' + event ؛
} ؛
}) (الأحداث [i]) ؛
}
من الواضح أن الحل الأول هنا هو خطأ في الحدث حلقة نموذجية. لن أشرح ذلك بالتفصيل هنا. يمكنك الرجوع إلى إجابتي إلى مستخدم الإنترنت بالتفصيل ؛ يكمن الفرق بين الحلول الثانية والثالثة في المعلمات التي تم تمريرها في الإغلاق.
المعلمات التي تم تمريرها في المخطط الثاني هي مركز الحلقة الحالي ، بينما يتم تمرير الأخير مباشرة إلى كائن الحدث المقابل. في الواقع ، فإن هذا الأخير أكثر ملاءمة لكميات كبيرة من تطبيقات البيانات ، لأنه في البرمجة الوظيفية في JavaScript ، فإن المعلمات التي تم تمريرها في مكالمات الوظائف هي كائنات الأنواع الأساسية ، وبالتالي فإن المعلمات الرسمية التي تم الحصول عليها في جسم الوظيفة ستكون قيمة نسخ ، بحيث يتم تعريف هذه القيمة على أنها متغير محلي في نطاق جسم الوظيفة. بعد اكتمال ربط الحدث ، يمكن إلغاء تغيير متغير الأحداث يدويًا لتقليل استخدام الذاكرة في النطاق الخارجي. علاوة على ذلك ، عندما يتم حذف عنصر ما ، يتم أيضًا تدمير وظيفة الاستماع إلى الحدث المقابلة ، وكائن الحدث ، ووظيفة الإغلاق وإعادة تدويرها.
3.6 الذاكرة ليست ذاكرة التخزين المؤقت
يلعب دور التخزين المؤقت في تطوير الأعمال دورًا مهمًا ويمكن أن يقلل من عبء موارد الفضاء. ولكن تجدر الإشارة إلى أنه يجب ألا تستخدم الذاكرة كذاكرة التخزين المؤقت بسهولة. الذاكرة هي شيء من كل شبر من الأراضي لأي تطوير للبرنامج. إذا لم يكن مورد مهم للغاية ، فالرجاء عدم وضعه مباشرة في الذاكرة ، أو صياغة آلية انتهاء الصلاحية لتدمير ذاكرة التخزين المؤقت للانتهاء تلقائيًا.
4. تحقق من استخدام ذاكرة JavaScript
في التطوير اليومي ، يمكننا أيضًا استخدام بعض الأدوات لتحليل استخدام الذاكرة واستكشافها في JavaScript.
4.1 وميض/متصفح ويب
في متصفح Blink/WebKit (Chrome ، Safari ، Opera ، إلخ) ، يمكننا استخدام أداة ملفات التعريف لأدوات المطورين لإجراء عمليات فحص الذاكرة على برامجنا.
4.2 فحص الذاكرة في Node.js
في Node.js ، يمكننا استخدام وحدات Node-Heapdump و Node-Memwatch لفحص الذاكرة.
نسخة الكود كما يلي:
var heapdump = require ('heapdump') ؛
var fs = require ('fs') ؛
var path = required ('path') ؛
fs.writeFilesync (path.join (__ dirname ، 'app.pid') ، process.pid) ؛
// ...
نسخة الكود هي كما يلي: <span style = "font-family: Georgia ، 'Times New Roman' ، 'Bitstream Charter' ، Times ، serif ؛ font-size: 14px ؛ line-height: 1.5em ؛ من ذاكرة الكومة. </span>
انسخ الرمز على النحو التالي: $ kill -usr2 (cat app.pid)
وبهذه الطريقة ، سيكون هناك ملف لقطة مسماة بتنسيق HeapDump- <ec>. <usec> .Heapsnapshot في دليل الملف. يمكننا فتحه باستخدام أداة ملفات التعريف في أدوات مطور المستعرض والتحقق منها.
5. ملخص
المقال قريبا مرة أخرى. يوضح لك هذه المشاركة بشكل أساسي المحتوى التالي:
1. يرتبط JavaScript ارتباطًا وثيقًا باستخدام الذاكرة على مستوى اللغة ؛
2. إدارة الذاكرة وإعادة التدوير آليات في JavaScript ؛
3. كيفية استخدام الذاكرة بشكل أكثر كفاءة بحيث يمكن أن يكون جافا سكريبت المنتج أكثر توسيعًا وحيوية ؛
4. كيفية إجراء عمليات فحص الذاكرة عند مواجهة مشاكل الذاكرة.
آمل أنه من خلال تعلم هذا المقال ، يمكنك إنتاج رمز جافا سكريبت أفضل لجعل والدتك تشعر بالراحة ويشعر رئيسك بالراحة.