Removing Object Properties in Js
فيه أكتر من طريقة عشان أقدر أحقق دا؟
عندي اتنين object والهدف بتاعي إني أخليهم similar
let object1 = { a: "hello", b: "world", c: "!!!", }; let object2 = { a: "hello", b: "world", };
عشان أحقق الهدف بكل بساطة ه delete the c property ودي الطرق اللي هنجربها عشان نحقق الهدف بالترتيب، والترتيب دا هيوصلنا لحاجة أهم من الهدف:
- هجرب إني أعمل set c to undefined
- هستخدم الـ delete operator
- هستخدم الـ proxy built-in object عن طريق إني هعمل deleted c property through a Proxy object
- فاكر الـ MUTATION إتكلمنا عليها قبل كدا هجرب إني أتجنبها عن طريق إني أستخدم object destructuring
- هستخدم JSON.stringify and JSON.parse
- rely on Lodash
يبقي هنجرب كل دول بالترتيب ونشوف هنوصل لإيه
I Set c To undefined
أول طريقة دي بالرغم من سطحيتها إلا أني هجربها لسبب ما تعال نعرفه مع بعض. لو قلتلك تعال ن
console.log(object1.d); // undefined
عشان مفيش عندي property إسمها d أصلا طب م تيجي نجرب ن Set c ل undefined
object1.c = undefined;
الـ output بقي ؟
let object1 = { a: "hello", b: "world", c: undefined, };
زي م انت شايف ال c هتفضل موجودة جوا الـ object1 رغم ان قيمتها undefined الـ approach دا مش بيعمل actually delete إنما بيغير القيمة بتاعة الـ property نتأكد بحاجة بسيطة:
const propertyExists = object1.hasOwnProperty("c"); console.log(propertyExists); // true
طب لو بجرب access property مش موجودة أصلا زي object1.d مش المفروض ت throw an error زي accessing a non-existing variable بيجيب ايرور زي دا
// Uncaught ReferenceError: اسم المتغير اللي مش موجود is not defined
طب ليه لما بأكسس object1.d بيجيب ليا undefined؟ الإجابة بكل بساطة هي انك تفهم ازاي الReferenceError بيbehaves وإيه هو أصلا؟
A reference is a resolved name binding that indicates where a value is stored. It consists of three components: a base value, the referenced name, and a strict reference flag.
عشان نفهم الكلام دا تعال نطبقه ع مثال لو عندك object of user وجواه name property فال user.name reference دي الـ baseValue بتاعتها ال user Object وال referenced name is the string, name وال strict reference flag دي بتبقي boolean value حسب انت في الـ strict mode ولا لا
الـ Variables بقي بت behave بطريقة مختلفة تماما لإنها معندهاش parent object ف بتكون الـ base value هي قيمة الـ environment record ف انت الـ base value دي بيحصلها assigned كل مرة الكود بيتنفذ
ف عشان كدا لما بتحاول تaccess أي حاجة ملهاش base value الـ JavaScript هتديك ReferenceError ومع ذلك لو الـ base value موجودة بس referenced name مبيعملش point لقيمة موجودة الـ JavaScript بكل بساطة هت assign الـ value لـ undefined
ودا من الـ ECMAScript Specification
“The Undefined type has exactly one value, called undefined. Any variable that has not been assigned a value has the value undefined.”
تاني طريقة وهي delete Operator
ودي هتمسح الـ property فعلا بس فيه بعض التحفظات لازم تأخدها ف الإعتبار قبل م تستخدمها أول تحفظ انك لو بتستخدمها مع الـ array
const movies = ["Interstellar", "Top Gun", "6 underground", "V for Vendetta"]; delete movies[2]; console.log(movies) // ["Interstellar", "Top Gun", empty , "V for Vendetta"];
هتلاقي بكل بساطة ان هي بتسيب مكانه فاضي ودا unexpected behavior هيسببلك مشاكل لو بتستخدم بعض الـ properties كـ length
console.log(movies.length); // 4
التحفظ التاني وهو
const user = { name: "Zezo", birthday: {day: 2, month: 11}, };
لو حاولت انك delete الـ birthday property هتشتغل كويس بس فيه misconception هنا مهم جدا وهو انك لما تعمل كدا دا frees up the memory allocated for the object ودا مبيحصلش
ليه بقي؟ ببساطة كلنا عارفين ان الـ JavaScript بت behave بشكل مختلف مع الـ Objects مقارنة بـ primitive values (e.g., numbers, strings, and booleans) بالذات ازاي بيتم تخزينهم ف الميموري
يعني لو انت بت Assign variable ب variable تاني ف الاتنين مش هيكونوا related ببعض وهيكونوا كل واحد منهم له independent space in memory
ع عكس لما بت Assign object بـ object تاني وبعدين تعدل property في الـ onbject دا بتلاقيها اتعدلت ف الاتنين واتأثرت عشان كل اللي بتعمله انك duplicating its reference و Under the hood, JavaScript looks at the actual object in memory and performs the change, and both references point to the changed object
طبعا الكلام دا انت عارفه دلوقتي نقدر نفهم ازاي delete operator doesn’t free space in memory
بص ي سيدي العملية اللي لغات البرمجة بت free memory بيها اسمها garbage collection في الـ JavaScript العملية دي بتتم مع الـ object لما ميكونش فيه أي حاجة بت reference له “is not needed anymore” عشان كدا using the delete operator مش هيكون مناسب معايا ف بعض الحالات وكمان ف بعض التحفظات ان هي بت impact on performance
تالت طريقة وهي Deleted The Property Through A Proxy Object
ايه هو الـ proxy الأول
A proxy is a way to insert some middle logic between an object’s common operations, like getting, setting, defining, and, deleting properties.
حلو؟ الـ Proxy بيأخد اتنين parameters
- target: The object from where we want to create a proxy.
- handler: An object containing the middle logic for the operations. يعني ببساطة بتديلها الـ object وتديلها الـ logic اللي عاوز تطبقه
جوا الـ handler احنا بنعرف methods لأي operations وبنسميها traps ليه بقي؟
because they intercept the original operation and perform a custom change
والنتيجة هتكون ان constructor هي return a Proxy object واللي هيكون identical للـ target بس with the added middle logic
تعال نبص ع مثال؟
const user = { name : "zezo", age: 24, }; const handler = { get(target, property) { return `user's ${property} is ${target[property]}`; }, }; const userProxy = new Proxy(user, handler); console.log(userProxy.name); // user's breed is zezo console.log(userProxy.age); // user's age is 24
في المثل دا الـ handler عمل modifies للـ getting operation عشان ت return a custom value
طب لو عاوز أ modifie الـ Deleting operation؟
const handler = { deleteProperty(target, property) { console.log(`Deleting property: ${property}`); }, };
هتحط دي جوا الـ handler ف لو جيت
const userProxy = new Proxy(user, handler); delete userProxy.name; // Deleting property: name هتلاقي دا الـ output ولو جيت ت javascript Copy code console.log(userProxy) // { name : "zezo", age: 24,};
متمسحتش! عشان إحنا ببساطة بدلنا الـ delete operator’s default behavior بـ custom behavior
اي اللي ييجي يلعب دور مهم هنا؟ بقي Reflect اي الـ reflect دي؟
Reflect is a global object with a collection of all the internal methods of an object. Its methods can be used as normal operations anywhere, but it’s meant to be used inside a proxy.
بص هنستفيد من Reflect ازاي ف مثالنا
const handler = { deleteProperty(target, property) { console.log(Deleting property: ${property}); return Reflect.deleteProperty(target, property); }, }; const userProxy = new Proxy(user, handler); delete userProxy.name; // Deleting property: name
في حاجة مهمة هنا لازم أنوه ليها ؟
في بعض ال built in objects زي Math, Date, and JSON وغيرهم مقدرش أ delete منهم عشان ببساطة هما “non-configurable” object properties يعني مينفعش أعملهم reassign or delete