التجميد السطحي مقابل العميق
افهموا مدى وصول عملية التجميد.
التجميد السطحي مقابل العميق درس مجاني في JavaScript Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في JavaScript Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة JavaScript Academy 4 دروس في المجموع.
التجميد سطحي
يقفل Object.freeze المستوى الأعلى من الكائن فقط. أما أي كائن أو مصفوفة متداخلة يشير إليها، فتظل قابلة للتغيير بالكامل.
يفاجئ هذا الأمر العديد من المطورين، ويسبب أخطاء دقيقة.
إثبات حدود التجميد السطحي
جمّد كائنًا يحتوي على كائن متداخل. يُقفل المستوى الأعلى، ولكن يظل بإمكانك تغيير الكائن المتداخل.
const user = Object.freeze({
name: 'Ada',
address: { city: 'London' }
});
user.name = 'Grace';
user.address.city = 'Paris';
console.log(user.name);
console.log(user.address.city);المصفوفات المتداخلة أيضًا
المصفوفات الموجودة داخل كائن مجمّد غير محمية أيضًا. يمكنك استخدام push وpop وإعادة إسناد عناصرها.
const state = Object.freeze({ tags: ['a', 'b'] });
state.tags.push('c');
state.tags[0] = 'X';
console.log(state.tags);يؤكد isFrozen ذلك
يُبلغ الكائن المتداخل عن قيمة isFrozen على أنها false، مما يؤكد أن التجميد لم يصل إلى داخله.
const obj = Object.freeze({ inner: { v: 1 } });
console.log(Object.isFrozen(obj));
console.log(Object.isFrozen(obj.inner));كتابة deepFreeze
لقفل كل شيء، استخدم الاستدعاء التكراري: جمّد الكائن، ثم جمّد كل خاصية تشير إلى كائن متداخل. يُسمى ذلك التجميد العميق.
function deepFreeze(obj) {
for (const key of Object.keys(obj)) {
const value = obj[key];
if (value && typeof value === 'object') {
deepFreeze(value);
}
}
return Object.freeze(obj);
}
const data = deepFreeze({ a: { b: { c: 1 } } });
data.a.b.c = 999;
console.log(data.a.b.c);deepFreeze مع المصفوفات
المصفوفات كائنات أيضًا، لذا يؤدي الاستدعاء التكراري نفسه إلى تجميدها. وعندها تُمنع عمليات الإضافة والكتابة إلى العناصر في كل مستوى.
function deepFreeze(obj) {
for (const key of Object.keys(obj)) {
const value = obj[key];
if (value && typeof value === 'object') deepFreeze(value);
}
return Object.freeze(obj);
}
const state = deepFreeze({ list: [1, 2, 3] });
state.list.push(4);
state.list[0] = 99;
console.log(state.list);التحقق من التجميد العميق
بعد التجميد العميق، يُبلغ كل كائن متداخل عن قيمة isFrozen على أنها true.
function deepFreeze(obj) {
for (const key of Object.keys(obj)) {
const v = obj[key];
if (v && typeof v === 'object') deepFreeze(v);
}
return Object.freeze(obj);
}
const o = deepFreeze({ a: { b: 1 } });
console.log(Object.isFrozen(o));
console.log(Object.isFrozen(o.a));الحماية من الحلقات
إذا كان الكائن يشير إلى نفسه، فسيستمر الاستدعاء التكراري الساذج إلى ما لا نهاية. تجاوز الكائنات المجمّدة مسبقًا لتبقى العملية آمنة.
function deepFreeze(obj) {
if (Object.isFrozen(obj)) return obj;
for (const key of Object.keys(obj)) {
const v = obj[key];
if (v && typeof v === 'object') deepFreeze(v);
}
return Object.freeze(obj);
}
const a = { name: 'a' };
a.self = a;
deepFreeze(a);
console.log(Object.isFrozen(a.self));تكلفة التجميد العميق
يزور التجميد العميق كل قيمة متداخلة، مما يستهلك وقتًا وذاكرة في البنى الكبيرة. جمّد فقط ما يحتاج فعلًا إلى الحماية، مثل الإعدادات المشتركة أو الثوابت.
function deepFreeze(obj) {
if (Object.isFrozen(obj)) return obj;
Object.keys(obj).forEach(k => {
const v = obj[k];
if (v && typeof v === 'object') deepFreeze(v);
});
return Object.freeze(obj);
}
const small = deepFreeze({ a: 1, b: { c: 2 } });
console.log('frozen deeply:', Object.isFrozen(small.b));متى يكون التجميد السطحي كافيًا؟
إذا كان الكائن يحتوي على قيم بدائية فقط، فإن Object.freeze السطحي يحميه بالكامل. ولا يصبح التجميد العميق مهمًا إلا عند وجود كائنات أو مصفوفات متداخلة.
const flat = Object.freeze({ a: 1, b: 'two', c: true });
flat.a = 100;
console.log(flat.a);
console.log(Object.isFrozen(flat));لماذا يهم هذا؟
يساعد فهم الفرق بين التجميد السطحي والعميق على تجنب الاعتقاد الخاطئ بأن الكائن المجمّد غير قابل للتغيير بالكامل. بالنسبة إلى البيانات المتداخلة، استخدم الاستدعاء التكراري. وبديلًا عن التغيير، تتناول الدروس التالية أنماط تحديث غير مُغيِّرة تنسخ البيانات بدلًا من تجميدها.
const config = Object.freeze({ db: { host: 'local' } });
config.db.host = 'changed';
console.log('shallow freeze leaked:', config.db.host);تحقق سريع
بعد تنفيذ Object.freeze({ a: { b: 1 } })، هل يمكنك تغيير b المتداخلة؟
مراجعة: التجميد السطحي مقابل العميق
لقد تعلّمت حدود التجميد من حيث العمق:
Object.freezeسطحي؛ لذلك تظل الكائنات والمصفوفات المتداخلة قابلة للتغيير.- يستخدم deepFreeze الاستدعاء التكراري لقفل كل مستوى.
- احمِ العملية من الحلقات بتجاوز الكائنات المجمّدة مسبقًا.
- للتجميد العميق تكلفة، لذا جمّد فقط ما يحتاج إلى الحماية.
الأسئلة الشائعة
هل درس «التجميد السطحي مقابل العميق» مجاني؟
نعم — نص درس «التجميد السطحي مقابل العميق» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة JavaScript Academy، انتقل إلى CoddyKit PRO. تتضمن دورة JavaScript Academy 4 دروس في المجموع.
ماذا ستتعلم في «التجميد السطحي مقابل العميق»؟
افهموا مدى وصول عملية التجميد. تتمرن على JavaScript Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ JavaScript Academy؟
لا تُشترط خبرة سابقة. JavaScript Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «التجميد السطحي مقابل العميق»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس JavaScript Academy هذا؟
نعم. كل درس في JavaScript Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- تجميد الكائنات وإغلاقها باستخدام Object.freeze وseal
- التجميد السطحي مقابل العميق
- أنماط التحديث غير القابل للتغيير
- structuredClone للنسخ العميقة