لقد اكتشفت للتو هذا المفهوم الصغير المثير للاهتمام للحفظ.
لقد بدأت قراءة المقال حول هذا الموضوع وتوقفت بمجرد أن أدركت ذيل الفكرة.
ثم قررت اكتشاف الحل البسيط بنفسي وبالطريقة التي أفهمها بها.
إذا لم تسمع بها من قبل، فإن الحفظ هو عملية تخزين نتائج تنفيذ الوظيفة، بحيث يمكنك سحبها من ذاكرة تخزين مؤقت صغيرة (أو غير ذلك) في المرة التالية التي تقوم فيها بتشغيل هذه الوظيفة بنفس الوسائط.
في الواقع يمكن أن يكون هذا مفيدًا لوظيفة تستهلك موارد عالية. يأتي مع تكلفة استخدام مساحة إضافية كذاكرة تخزين مؤقت. ولكن يمكنها تحسين سرعة التعليمات البرمجية الخاصة بك وتجربة المستخدمين الذين يستخدمونها.
لقد استخدمت كود JS قليلًا وتوصلت إلى هذا الحل:
const memoize = fn => { const cache = {} return (...args) => { const fnKey = `${fn.name}(${args})`; if(!cache[fnKey]) { cache[fnKey] = fn(...args); } return cache[fnKey] }; }
ثم يمكنك تشغيله بهذه الطريقة:
function _add(x, y) { console.log("function runs", x, y); return x y; } const add = memoize(_add) add(42, 69) add(10, 15) add(10, 15)
يؤدي ذلك إلى تنفيذ الوظيفة مرتين (مكالمات "إضافة" رقم 1 ورقم 2). ستستخدم مكالمة "الإضافة" الثالثة ذاكرة التخزين المؤقت لأنها مماثلة للمكالمة رقم 2.
'function runs' 42 69 'function runs' 10 15
يمكنك أن ترى أن "تشغيل الوظيفة" 10 15 يتم استدعاؤه مرة واحدة فقط. وذلك لأنه في المرة الثانية التي نسميها، يتم استخدام ذاكرة التخزين المؤقت.
الآن دعونا نحلل بسرعة ما يحدث هنا.
في هذا المثال نستخدم آلية الإغلاق لتخزين ذاكرة التخزين المؤقت.
const memoize = fn => { const cache = {} return () => { }; }
يسمح لنا هذا بإلقاء وسيطة "fn"، وهي ملك المجموعة لأن هذه هي بالضبط الوظيفة التي نريد العمل بها، أسفل النطاقات و"الاستماع" إلى كل عملية تنفيذها.
لقد كتبتها حقًا بالطريقة الأكثر بساطة وسذاجة. لذلك سوف نستخدم اسم الوظيفة مع الوسائط كمفاتيح لذاكرة التخزين المؤقت، ونتائج تنفيذها كقيم.
وهذا يعني أن التنفيذ:
add(2, 2)
النتائج في
// Our cache { 'add(2, 2)': 4 }
قيمة ذاكرة التخزين المؤقت.
أعلم أن هذا ربما لا يكون بالضبط الطريقة التي ينبغي أن يتم بها "بالطريقة الصحيحة". لكن فكرة هذا التمرين والمقالة لا تتعلق بالحل الآمن والمجاني الذي تم اختباره جيدًا.
يتعلق الأمر بالتعلم والتنفيذ البسيط. حول هذا المفهوم. لذلك أنا لا أركز على تفاصيل التنفيذ الآن.
الآن، نكتشف أولاً مفتاح استدعاء الوظيفة:
const memoize = fn => { const cache = {} return (...args) => { const fnKey = `${fn.name}(${args})`; }; }
سنستخدمه لتخزين نتائج تنفيذ الوظيفة في ذاكرة التخزين المؤقت.
ثم نتحقق مما إذا كان هذا المفتاح (fnKey) موجودًا بالفعل. إذا لم يكن الأمر كذلك، فإننا نضبط المفتاح بقيمته نتيجة لتنفيذ الوظيفة التي تم تمريرها.
في النهاية نقوم دائمًا بإرجاع النتيجة من ذاكرة التخزين المؤقت. لذا فإن تنفيذ الوظيفة التي تم تمريرها إلى طريقة الحفظ ينتهي دائمًا بالإغلاق (في كائن "ذاكرة التخزين المؤقت").
نحن نعمل فقط مع هذا الكائن الآن:
const memoize = fn => { const cache = {} return (...args) => { const fnKey = `${fn.name}(${args})`; if(!cache[fnKey]) { cache[fnKey] = fn(...args); } return cache[fnKey] }; }
وهذا كل شيء.
الآن سأذهب وأرى كيف ينبغي القيام بذلك "بشكل صحيح". ولكن إذا وجدت هذا مثيرًا للاهتمام، فأخبرني بذلك. إذا كان هناك شيء غير واضح أو خاطئ في هذا النهج (حسب ذوقك)، فما عليك سوى إسقاط التعليق ودعنا نتحدث عنه.
شكرًا، إلى اللقاء!
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3