AG Coding
1.27K subscribers
488 photos
52 videos
8 files
241 links
Some Challenges And Applications On Frontend Development
maded By @abdoelazizgamal
Don't Forget Follow And Subscribe My
Youtube channel
https://www.youtube.com/c/AbdoELAzizGamal?sub_confirmation=1
Download Telegram
إمتى ظهر الـ Shadow DOM، وظهر ليه، وأهميته إيه؟

مع تقدم تطوير الويب، بقت التطبيقات بتعتمد على libraries و framewoorks زي React وVue.js. ومع تزايد التعقيد في الـUI components، بقت مشكلة إدارة الـstyles والـscripts جوه الـindividual components بتزيد.

المشكلة
قبل ما يظهر الـShadow DOM، كان عندنا مشكلة كبيرة في الـCSS bleeding. لو عندك component معقد، الـstyles بتاعته كانت ممكن تتداخل مع الـstyles بتاعة مكونات تانية في الصفحة. ده بيخلي الحفاظ على الـstyles بشكل منظم ومستقل لكل component عملية صعبة.

ظهور الـShadow DOM
الـShadow DOM ظهر كجزء من الـWeb Components standard علشان يحل المشكلة دي. الـShadow DOM بيوفر بيئة معزولة لأي component، بحيث الـstyles والـscripts جوه الـcomponent ده ما يتأثروش بأي حاجة تانية في الصفحة.

إزاي بيشتغل؟
الـShadow DOM بيشتغل عن طريق إنشاء شجرة DOM مستقلة لكل component. لما بنستخدم الـShadow DOM، بنقدر نعمل encapsulation للـHTML، CSS، والـJavaScript بتاع الـcomponent ده.

مثال بسيط:
class MyComplexElement extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML =
<style>
p {
color: green;
}
</style>
<slot name="my-text"></slot>
<button id="myButton">Click me</button>
;
const button = shadow.querySelector('#myButton');
button.addEventListener('click', () => {
alert('Button inside Shadow DOM clicked!');
});
}
}

customElements.define('my-complex-element', MyComplexElement);


المميزات
Encapsulation
الـstyles جوه الـShadow DOM ما بيأثروش على بقية الصفحة.
Reusability
الـWeb Components بقت أسهل في إعادة الاستخدام.
Maintainability
بقت عملية صيانة الكود أسهل لإن كل component بيبقى مستقل بذاته.

قبل وبعد الـShadow DOM
الـstyles بتتداخل مع بعضها.
صعوبة في إعادة استخدام الكود بدون مشاكل في الـstyles

بعد الـShadow DOM
كل component عنده بيئة معزولة.
سهولة في إعادة استخدام الـWeb Components بدون مشاكل في الـstyles.

الخلاصة
الـShadow DOM قدم حل فعال لمشكلة الـCSS bleeding وخلى إدارة الـWeb Components أسهل وأكتر تنظيماً. مع التقدم في الـWeb standards، بقى الـShadow DOM أداة مهمة خاصة ل (SPAs) والـProgressive Web Apps (PWAs) لأنه بيساعد في تنظيم الكود وتحسين الأداء.

التوافق مع المتصفحات
دعم الـShadow DOM زاد بشكل كبير في السنوات الأخيرة، لكن بعض المتصفحات القديمة قد تحتاج لـpolyfills.

مقارنة بين الـShadow DOM وحلول تانية زي CSS Modules أو CSS-in-JS:
Shadow DOM
بيقدم encapsulation للـstyles والـscripts بشكل مستقل.
CSS Modules
بتوفر scope للـstyles بدون تغييرات في الـDOM.
CSS-in-JS
بتمكنك من كتابة الـstyles جوه JavaScript، مما يديك تحكم أكتر.

مثال عملي أكثر تعقيداً بيوضح كيفية التعامل مع الـevents والـslots في الـShadow DOM


class MyComplexElement extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML =
<style>
p {
color: green;
}
</style>
<slot name="my-text"></slot>
<button id="myButton">Click me</button>
;
const button = shadow.querySelector('#myButton');
button.addEventListener('click', () => {
alert('Button inside Shadow DOM clicked!');
});
}
}

customElements.define('my-complex-element', MyComplexElement);



التطورات المستقبلية المتوقعة للـShadow DOM بتتضمن تحسين الـintegration مع تقنيات ويب جديدة، زي دعم أكتر لـAR/VR والـWebAssembly.



ودا مثال إزاي تستخدم ال shadow dom مع react

import React, { useRef, useEffect } from 'react';

function ShadowComponent() {
const hostRef = useRef(null);

useEffect(() => {
const shadow = hostRef.current.attachShadow({ mode: 'open' });
shadow.innerHTML =
<style>
p { color: blue; }
</style>
<p>This is inside Shadow DOM</p>
;
}, []);

return <div ref={hostRef}></div>;
}
3👍1
تعال أقولك شوية features جديدة في ال js عشان تبقي جامد جمودة
نبدأ بال Optional Chaining (?.)
الـ Optional Chaining إتضافت في ال ECMAScript 2020. بتسمحلك توصل لقيمة جوا objects متشعبة من غير ما تعمل if conditions كتير. يعني بدل ما تتأكد من وجود كل جزء في Chain تقدر تستخدم الـ Optional Chaining بشكل بسيط:
let streetName = person?.address?.street?.name;
لو الشخص مش موجود أو العنوان مش موجود، الكود مش هيعمل خطأ وهيرجع undefined.

———-
Nullish Coalescing (??)

الـ Nullish Coalescing Operator اتقدمت برضه في ECMAScript 2020. دي بتستخدم علشان ترجع أول قيمة لو مش null أو undefined، وتاني قيمة لو الأولانية null أو undefined. يعني مثلاً:
let name = person?.name ?? 'Unknown';
لو الشخص مش عنده اسم، هيرجع 'Unknown' بدل ما يرجع undefined.
———
BigInt
ده نوع بيانات جديد في JavaScript اسمه BigInt. بيستخدم لتمثيل الأعداد الكبيرة جداً اللي ماينفعش تتعامل معاها بـ Number العادي. يعني ممكن تكتب:
const bigNumber = 12345678901234567890n;
الأعداد دي ممكن تكون أكبر بكتير من أكبر رقم يقدر يتعامل معاه الـ Number العادي وبالمناسبة هي primitive data type
————
globalThis

ده global object جديد في JavaScript اسمه globalThis. بيوفر طريقة للوصول للـ global object بطريقة متوافقة مع كل بيئات JavaScript الحديثة زي المتصفحات و Node.js. يعني بدل ما تكتب window أو global، تقدر تكتب:
console.log(globalThis === window); // true في المتصفح

—————
matchAll()

دي method جديدة على الـ String prototype، اسمها matchAll(). بتديك Iterator بيجيب كل المتطابقات مع Regular Expression في نص، وبتشمل الـ capturing groups. مثال:
const regex = /(\w)(\d)/g;
const str = 'a1b2c3';
for (const match of str.matchAll(regex)) {
console.log(match);
}

الكود ده هيطبع كل المتطابقات زي ['a1', 'b2', 'c3'].

——-
Promise.allSettled()

دي method جديدة في API بتاع Promise، اسمها allSettled(). بترجع promise بيتحل لما كل الـ promises في المصفوفة تتحل سواء كانت تحلت أو ترفضت. مثال:

const promises = [Promise.resolve('a'), Promise.reject('b'), Promise.resolve('c')];
Promise.allSettled(promises).then((results) => console.log(results));

الكود ده هيطبع الحالة بتاعة كل promise سواء كان تحل أو ترفض.
—————
String.prototype.at()

دي method جديدة على الـ String prototype، اسمها at(). بترجع الحرف عند الـ index المحدد، وبتسمح باستخدام مؤشرات سالبة للوصول للحروف من آخر النص. مثال:
const str = 'hello';
console.log(str.at(0)); // 'h'
console.log(str.at(-1)); // 'o'
—————————


Error Cause

الـ Error Cause هي خاصية جديدة في JavaScript بتسمحلك تضيف معلومات عن السبب الأصلي للخطأ لما ترمي (throw) خطأ جديد. الفكرة هي إنك لما يكون عندك خطأ، أحياناً بيكون السبب الأصلي للخطأ خطأ تاني، والخاصية دي بتساعدك تحتفظ بالمعلومات دي ، مثال بسيط

بدون Error Cause
لو ما استخدمتش Error Cause، هيبقى عندك كود زي ده:

try {
// تخيل إن دي دالة بتقرأ ملف
readFile('nonexistentFile.txt');
} catch (originalError) {
throw new Error('Failed to read file');
}
في الحالة دي، الخطأ الجديد "Failed to read file" مش هيحتوي على تفاصيل الخطأ الأصلي.

باستخدام Error Cause
لو استخدمت Error Cause، هيبقى عندك كود زي ده:
try {
// تخيل إن دي دالة بتقرأ ملف
readFile('nonexistentFile.txt');
} catch (originalError) {
throw new Error('Failed to read file', { cause: originalError });
}
إزاي تستخدمها
لما ترمي خطأ جديد، ممكن تضيف الخاصية cause وتحدد الخطأ الأصلي. بعد كده، لما تعمل كاتش (catch) للخطأ، تقدر تطبع أو تستخدم السبب الأصلي للخطأ.

try {
try {
// دي دالة بتعمل حاجة ممكن تفشل
doSomethingRisky();
} catch (originalError) {
throw new Error('Something went wrong', { cause: originalError });
}
} catch (error) {
console.log(error.message); // "Something went wrong"
console.log(error.cause); // يطبع الخطأ الأصلي
}
الفوائد
توفير معلومات إضافية: يساعدك في تتبع أسباب الأخطاء بسهولة أكبر.
تحليل أفضل للأخطاء: لما يكون عندك سلسلة من الأخطاء، تقدر تفهم السياق الكامل للخطأ بسهولة.
تحسين تجربة التطوير: بيخلي عملية الديباجينج (debugging) أسهل وأسرع.
باختصار، الـ Error Cause بتخليك تقدر تضيف سبب إضافي للخطأ بحيث تقدر تتبع الأخطاء بشكل أفضل وتفهمها بشكل أعمق، خصوصاً لما يكون عندك أكتر من مستوى من الخطأ في الكود بتاعك.
1🥰1
عاوز prebuild components وتكون customizable و الFocus فيها كله إنها تساعدك تبني dashboard ؟
وال style بتاعها إتبني علي ال tailwind عرفت ليه fully customizable ؟
خد و إدعيلي ..

https://raw.tremor.so/docs/getting-started/installation
2🥰2
زمان قبل 2010، كان مصممي الويب يقدروا يعملوا مواقع تناسب الديسكتوب بس. لحد ما جه Ethan Marcotte وقدم لنا مفهوم الـResponsive Web Design (RWD)، واللي عرفه موقع MDN بأنه طريقة لتصميم الويب عشان يناسب كل الأجهزة. وده خلى الـmedia queries عنصر أساسي في الRWD .
لكن دلوقتي في تحول ناحية حاجة جديدة عرفتها Jen Simmons بـIntrinsic Web Design – اللي بتركز على عمل مكونات بتفهم السياق اللي هي فيه. وContainer Queries هي اللي بتخلي ده ممكن.



مقارنة بين Media Queries و Container Queries في ال CSS

الweb development بيتطور بسرعة، وعشان تواكب التطورات دي لازم تكون فاهم الأدوات الجديدة زي Container Queries وكمان الأدوات التقليدية زي Media Queries. في البوست دا، هنوضح بالتفصيل استخدامات كل أداة، المزايا والعيوب، وازاي تقدر تستفيد منها بأفضل شكل في مشاريعك.
نبدأ بال Media Queries
هي واحدة من أدوات CSS الأساسية اللي بنستخدمها عشان نخلي التصميم responsive ويتغير بناءً على حجم الشاشة أو نوع الجهاز. لما نستخدم Media Queries، بنحدد نقاط معينة (breakpoints) اللي عندها التصميم يتغير.
ال Media Queries
بتسمح لك تعمل تصميم يناسب كل أحجام الشاشات والأجهزة
أغلب مصممي الويب بيكونوا عارفينها ومتعودين عليها
ولكن
مش بتديك تحكم كبير في تعديل العناصر الداخلية لوحدها وركز علي لوحدها دي
لو عندك تصميمات معقدة، ممكن تلاقي نفسك مضطر تكتب كود كتير عشان تغطي كل الحالات
مثال بالكود
@media (max-width: 768px) {
.container {
flex-direction: column;
}
}

نيجي بقي لل Container Queries
جديدة في CSS وبتديك إمكانية تغير التصميم بناءً على حجم الكونتينر اللي العنصر جواه، مش حجم الشاشة. ده بيساعد في تصميم مكونات (components) أكثر مرونة واستقلالية حلو دا عشان ال Reusability
و بتقدر تغير التصميم بناءً على المساحة المتاحة للعنصر بشكل مستقل
ممتازة لتصميمات المكونات اللي بتكون جزء من تصميم أكبر
ولكن
لسه جديدة ومش مدعومة في كل المتصفحات
هتاخد شوية وقت عشان تتعود عليها
شوف بقالك قد إيه بتكتب media queries
مثال بالكود
.header {
container: mysite / inline-size;
}

@container mysite (min-width: 600px) {
.maincard {
grid-template-columns: 1fr 1fr;
}
.item {
background-color: green;
}
}

ركزلي شوية دا ال Syntax
container: [name] / [type];
اسم الكونتينر اللي هتستخدمه في الـContainer Queries
نوع القياس اللي هتستخدمه (inline-size لعرض الكونتينر، block-size لطول الكونتينر)


خاصية inline-size في CSS بتحدد الحجم الأفقي أو الرأسي لكتلة العنصر بناءً على نمط الكتابة المستخدم. لو نمط الكتابة بيكون من اليسار لليمين (مثل اللغة الإنجليزية)، فالـ inline-size هتكون العرض. ولو نمط الكتابة بيكون من الأعلى للأسفل (مثل اللغة الصينية التقليدية)، فالـ inline-size هتكون الطول.
خاصية block-size في CSS بتحدد الحجم الرأسي أو الأفقي لكتلة العنصر بناءً على نمط الكتابة المستخدم. لو نمط الكتابة بيكون من اليسار لليمين، فالـ block-size هتكون الطول. ولو نمط الكتابة بيكون من الأعلى للأسفل، فالـ block-size هتكون العرض.

معلش دي شوية حاجات لازم توضح
في المثال ده، احنا عرفنا كونتينر اسمه mysite ونوع القياس هو inline-size. لما عرض الكونتينر يبقى 600 بيكسل أو أكتر، هتتغير خصائص العناصر جوا الكونتينر.
الميزة بقي في ال Container Queries ال Modularity and Flexibility
يعني كمثال علي دا
تخيل عندك Card component اللي ممكن تستخدمه في أماكن مختلفة في الموقع. باستخدام Container Queries، تقدر تخلي التصميم بتاع الكارد يتغير بناءً على حجم الكونتينر اللي هو فيه.
سهولة إعادة الاستخدام، المكونات اللي بتستخدم Container Queries بتكون سهلة في إعادة الاستخدام في مشاريع مختلفة أو في أجزاء مختلفة من نفس المشروع.

إمتى تستخدم كل واحدة فيهم؟

Media Queries: لما تكون بتشتغل على تصميم استجابي تقليدي وعاوز تغييرات بناءً على حجم الشاشة.
Container Queries: لو عندك تصميم معقد فيه مكونات كتير بأحجام مختلفة عاوز تعدلها بشكل مستقل.
4🥰1
إعمل save للبوست أو share هتحتاجه كدا كدا ...
عاوز تبقي software engineer جامد جمودة ؟
البوست دا هيبقي refrence لل GitHub Repositories و هصنفهالك categories

يعني لو إنت شخص بتدور علي github repositories لل RoadMaps

1 - https://github.com/kamranahmedse/developer-roadmap
2 - https://github.com/liuchong/awesome-roadmaps

بتدور علي github repositories لل Books, Blogs, and Websites
1 - https://github.com/EbookFoundation/free-programming-books
2 - https://github.com/kilimchoi/engineering-blogs
3 - https://github.com/sdmg15/Best-websites-a-programmer-should-visit
4 - https://github.com/freeCodeCamp/freeCodeCamp

بتدور علي github repositories لل Algorithms
1 - https://github.com/TheAlgorithms
2 - https://github.com/arpit20adlakha/Data-Structure-Algorithms-LLD-HLD
3 - https://github.com/tayllan/awesome-algorithms

بتدور علي github repositories لل Algorithms
1 - https://github.com/kamranahmedse/design-patterns-for-humans
2 - https://github.com/DovAmir/awesome-design-patterns

بتدور علي github repositories لل System Design
1 - https://github.com/ByteByteGoHq/system-design-101
2 - https://github.com/donnemartin/system-design-primer
3 - https://github.com/InterviewReady/system-design-resources
4 - https://github.com/karanpratapsingh/system-design

بتدور علي github repositories للDesign Resources
1 - https://github.com/goabstract/Awesome-Design-Tools
2 - https://github.com/bradtraversy/design-resources-for-developers

بتدور علي github repositories لل Projects, Tutorials, and APIs

1 - https://github.com/florinpop17/app-ideas
2 - https://github.com/practical-tutorials/project-based-learning
3 - https://github.com/public-apis/public-apis


بتدور علي github repositories لل Interviews
1 - https://github.com/kdn251/interviews
2 - https://github.com/yangshun/tech-interview-handbook
3 - https://github.com/DopplerHQ/awesome-interview-questions
2🥰1
هل إنت من المبرمجين الشريرين ولا مبرمج طيوب لذوذ ؟
متستغربش تعال أقولك سيناريو غريب شوية،حازم بيستخدم موقعك من نفس المتصفح اللي بيخش بيه ع موقع زي ٱموالي أو موقع البنك يخلص معاملاته الرقمية ، واللي بيفتح منه برضه جيميل
ف طبعا المتصفح بيخزن ال cookies بتاعة حازم
طبعا إنت عارف الconcept بتاع AJAX
(Asynchronous JavaScript And XML)
طب م أحاول في موقعي
أعمل كود JavaScript يجيبلي بيانات حازم من المتصفح وبعدين أستخدم AJAX علشان أبعت ريكوست عشان أخزن بيانات حساب حازم أو أبعت ريكوست للجيميل كأني حازم
stoooooooooooooooop
بس ومتسرحش بخيالك ي نجم
مفيش حاجة من دي هتحصل عشان تفهم ليه
هنا بقى ييجي دور SOP
قبل ما نخش في التفاصيل، لازم نفهم حاجتين مهمين:
SOP (Same-Origin Policy)
CORS (Cross-Origin Resource Sharing)

SOP
ده بيوفر أمان أساسي. ببساطة، بيمنع أي موقع (زي موقعك كمبرمج شرير ) من إنه يقرأ البيانات أو الكوكيز من موقع تاني (زي جيميل) إلا لو الاتنين من نفس الأصل (الدومين، البروتوكول، والبورت).
يعني متقدرش تقرأ كوكيز الجيميل إلا لو إنت ال gmail !
CORS:
ده بقى زي المساعد لـSOP، بيدي استثناءات، يعني يسمح لبعض المواقع إنها تبادل بيانات مع بعضها بشروط معينة
____

واحدة واحدة بقي ، السيناريو اللي إنت كنت عاوز تعمله دا كمبرمج مش لذوذ إسمه CSRF
(Cross-Site Request Forgery)
يعني إيه يعني بستغل الثقة بتاعة حازم فيا كموقع وأستخدم الكوكيز الخاصة بيه لعمل تحويل مالي من حسابه لحسابي ..
العملية مش سهلة كدا ي نجم أولا ف أدوات حماية مختلفة
نبدأ ب
SOP (Same Origin Policy)
ودي زي م قلتلك مش هيسمح لأي سكريبتات على "example.com" إنها تقرأ البيانات بتاعتك من "anotherdomain.com" أو تبعت ريكوستات له يعني من الأخر بيضمن أن المواقع الضارة مش قادرة على الوصول إلى الكوكيز أو الموارد من دومين تاني بدون إذن.
تاني حاجة
HttpOnly Attribute
ودي ببساطة خاصية بتضاف للكوكيز بتخليها مش accesible من ال JavaScript.
لما الكوكيز تكون عليها HttpOnly، مش ممكن للسكريبتات اللي على المتصفح قراءة الكوكيز دي، وده بيحميها من هجمات
XSS (Cross-Site Scripting).
تالت حاجة وهي ال SameSite Attribute
هو خاصية تانية في الكوكيز بتحدد مدى مرونة إرسال الكوكيز بين المواقع. فيه ثلاث قيم رئيسية للخاصية دي:

Strict:
الكوكيز هتترسل بس مع الطلبات اللي جايه من نفس النطاق.
Lax:
الكوكيز هتترسل مع الطلبات اللي جايه من نفس النطاق وأيضًا مع الطلبات من روابط من مواقع أخرى، ولكن فقط مع بعض الطلبات زي GET.
None:
الكوكيز هتترسل مع الطلبات عبر المواقع المختلفة بدون قيود، ولكن لازم يكون الطلب عبر HTTPS.

_
يبقي كده SOP
بيوفر الحماية من الوصول الغير مصرح به بين الdomains.
HttpOnly
بيوفر الحماية للكوكيز من الوصول عبر JavaScript، مما يساعد في الحماية من XSS.
SameSite
بيوفر حماية مخصصة ضد CSRF من خلال تحديد متى وأين يمكن إرسال الكوكيز.
التكامل بين الثلاث أدوات دي بيوفر layers للحماية ضد مجموعة متنوعة من التهديدات، بما في ذلك CSRF، XSS، والتهديدات الأخرى المتعلقة بالكوكيز.


ف من الأخر السيناريو باعك كمبرمج شرير باظ ليه بقي ؟
في حالة المواقع الكبيرة زي جيميل، الكوكيز عادةً ما بتكون محمية بخصائص إضافية غير HttpOnly، زي:
إستخدام خاصية SameSite في الكوكيز بتاعتهم لتقليل فرص هجمات CSRF.
استخدام (CSRF Tokens)
المواقع الكبيرة بتضيف (CSRF Tokens) في الformsِ والطلبات الحساسة. الرموز دي بتكون فريدة لكل session وكل request
Token Validation
لما المستخدم يبعت طلب (POST request مثلا)،
الموقع بيتأكد إن الرمز اللي جاي مع الطلب هو نفس الرمز اللي الموقع أصدره للمستخدم ده.
لو الرمز مش مطابق، الطلب بيرفض.

تفعيل CORS بشكل محدود
CORS (Cross-Origin Resource Sharing):
المواقع الكبيرة بتستخدم إعدادات CORS بشكل محدود عشان تسمح لبعض الdomains الموثوقة بالوصول للموارد، وبكده تمنع الdomains الغير مصرح بها.


Content Security Policy (CSP)
المواقع بتستخدم CSP لتحديد المصادر المسموح لها بالتحميل والتشغيل على الصفحة، مما يقلل فرص تنفيذ كود ضار على الموقع.
Secure Attribute:
الكوكيز بتاعت الجلسات بتكون عليها خاصية Secure عشان يتم إرسالها بس عبر اتصالات HTTPS، وده بيمنع تسرب الكوكيز عبر اتصالات مش encrypted
4🥰1
عاوز تعمل Face detection بال js ؟
https://justadudewhohacks.github.io/face-api.js/docs/index.html
دي JavaScript API built on the tensorflow.js core
لل face detection وال face recognition في الbrowsers
2🥰1
إيه الجديد في JavaScript
ال ECMAScript® 2024 (ES15) متستغربش :(
إنت بتكبر والjs بتكبر معاك !
الكلام دا كله قالوا إن هيطبق السنة دي :( إن عشنا وكان لنا من العمر بقية
نبدأ بسم الله بأول حاجة
Temporal.Now.Instant()

في استبيان State of JS 2022، السؤال عن "إيه اللي ناقص حاليًا في JavaScript؟" كان الإجابة التالتة الأكثر شيوعًا هيDate Management بشكل أفضل
ده خلى فيه اقتراح اسمه "Temporal"، اللي بيقدّم standard global object هي replace the Date object
العمل مع التواريخ في JavaScript عادةً بيكون مُزعج جدًا؛ لأن فيه بعض التناقضات الصغيرة ، زي إن الشهور بتبدأ من صفر بينما الأيام في الشهر بتبدأ من 1.
الصعوبة في التعامل مع التواريخ أدت لظهور مكتبات مشهورة زي Moment و Day.js و date-fns اللي حاولت تحل المشاكل دي. لكن الـ Temporal API بيهدف إنه يحل كل المشاكل دي built in في اللغة نفسها
ايه الجديد في Temporal؟
هيدعم تعدد ال Time Zones وتقويمات مختلفة غير ال Non-Gregorian
هيوفرلك simple API هتسهل عليك التعامل مع التواريخ وتحليلها من الstrings
all Temporal objects will be immutable
ده هيساعدك تتجنب الأخطاء اللي بتحصل لما التواريخ بتتغير بدون قصد.
const instant = Temporal.Now.Instant();
console.log(instant); // هيرجع الوقت الحالي بدقة النانوثانية
هتوفرلك شوية apis عنب زي
PlainDate()
PlainTime()
PlainMonthDay()
PlainYearMonth()
const today = Temporal.Now.plainDateISO();
const lastWeek = today.subtract({ days: 7});
const nextWeek = today.add({ days: 7 });
وهسيبك بقي تعيش في خيالك معاهم لحد م تجربهم بنفسك

في نفس استبيان State of JS 2022
كان الجواب السادس في إيه ناقص ال JavaScript
هو ال Pipe Operator
إيه هو ؟
الـ Pipe Operator ده ميزة موجودة في لغات البرمجة اللي بتكون functional languages واللي بتخليك "تمرر" قيمة من دالة لدالة تانية،
يعني الناتج من الدالة الأولى بيتستخدم كمدخل للدالة اللي بعدها، بشكل مشابه للطريقة اللي فيها Fetch API بيعدي البيانات اللي بترجعها من وعد (Promise) للثاني.
مثال
دول 3 js functions
const exclaim = string => string + "!!!";
const listen = string => "Listen up! " + string;
const uppercase = string => string.toUpperCase();
الـ 3 دوال دي ممكن تطبقهم بنظام ال nesting



const text = "Hello World";

uppercase(exclaim(listen(text)));
// << "LISTEN UP! HELLO WORLD!!!"


بالطريقة دي مش دايمًا بيكون مناسب وبيخلي الكود أصعب في القراءة، خصوصًا لما يكون عندك دوال أكتر من كده. هنا بيجي دور الـ Pipe Operator، اللي بيسهل التعامل مع الدوال المتتالية ويخلي الكود أوضح وأبسط.
const exclaim = string => string + "!!!";
const listen = string => "Listen up! " + string;
const uppercase = string => string.toUpperCase();

const text = "Hello World"

uppercase(exclaim(listen(text)))
<< "LISTEN UP! HELLO WORLD!!!"
ممكن تعمل الكلام دا بال function chaining
const text = "Hello World"

text.listen().exclaim().uppercase()
للأسف، المثال ده مش هيشتغل، لأن دوال listen, exclaim, وuppercase مش methods في كلاس الـ String. ممكن نضيفهم عن طريق الـ monkey patching لكلاس الـ String، لكن ده عمومًا مش مستحب كطريقة.
ده معناه إنه رغم إن الـ chaining شكله أفضل من التداخل (nesting)، لكنه فعليًا ممكن يتستخدم بس مع الدوال المدمجة في اللغة (زي ما بنشوف مع دوال الـ Array).

الـ Piping بيجمع بين سهولة الـ chaining بس مع القدرة على استخدامه مع أي دوال. تحت الاقتراح الحالي، المثال اللي فوق هيكون مكتوب بالشكل ده:


const text = "Hello World";

// باستخدام الـ Pipe Operator
const result = text
|> listen
|> exclaim
|> uppercase;

console.log(result); // "LISTEN UP! HELLO WORLD!!!


خلينا نكمل الباقي ف مقالة تانية :((
3👍2
AG Coding
إيه الجديد في JavaScript ال ECMAScript® 2024 (ES15) متستغربش :( إنت بتكبر والjs بتكبر معاك ! الكلام دا كله قالوا إن هيطبق السنة دي :( إن عشنا وكان لنا من العمر بقية نبدأ بسم الله بأول حاجة Temporal.Now.Instant() في استبيان State of JS 2022، السؤال…
part 2 !!!!!!
من ال js بتكبر وإنت بتكبر معاها
تالت حاجة هي
Records and Tuples
لو إنت جاي من لغة برمجة زي بايثون ف هتسأل هل Tuples موجودة ف ال js ، الحقيقة لا بس تقدر تعملها simulation بإستخدام Object.seal()
let arr = new Array(1, 0, 0);
let tuple Object.seal(arr)

أو هتستخدم ال Proxy
طب إيه الهدف إنهم يضيفوا حاجة زي دي للjs ببساطة كل الهدف إنها تضيف immutable data structures to JavaScript.

ال (Tuples) شبه الِarrays - لستة مترتبة من القيم - لكن مش ممكن تتغير (immutable). ده معناه إن كل قيمة في Tuples لازم تكون يا إما قيمة (primitive) يا إما Record تاني أو Tuple تاني (مش arrays أو objects لإنهم ممكن يتغيروا في الجافاسكريبت).

الTuple بيتعمل بطريقة مشابهة للأراي العادية، بس بتحط علامة الشباك (#) في الأول:
const heroes = #["Batman", "Superman", "Wonder Woman"]
بعد ما تعمل التوبل ده، مش ممكن تضيف قيم تانية أو تشيل قيم. القيم نفسها كمان مش ممكن تتغير.

ال (Records) شبه الobjects - مجموعة من ال (key-value pairs) - لكن برضه مش ممكن تتغير. بتتعمل بطريقة مشابهة للobjects، بس برضه بتحط علامة الشباك في الأول:
const traitors = #{
diane: false,
paul: true,
zac: false,
harry: true
}

الRecords هتستخدم الـ dot notation عشان توصل للproperties and methods
traitors.paul
<< true

وكمان الـ square bracket notation اللي بتستخدم مع ال arrays ممكن تستخدمها مع الtuples:
heroes[1]
<< "Superman"

بس لإنهم ثابتين (immutable)، مش هتقدر تعدل أي خصائص:

traitors.paul = false
<< Error

heroes[1] = "Supergirl"
<< Error


الimmutability of tuples and records يعني إنك هتقدر تقارن بينهم بسهولة باستخدام operator(===):

heroes === #["Batman", "Superman", "Wonder Woman"];
<< true

حاجة لازم تاخد بالك منها إن ترتيب الproperties مش بيهم لما تيجي تقارن بين الrecords
traitors === #{
ross: false,
zac: false,
paul: true,
harry: true
};
// still true, even though the order of people has changed
<< true
:
الترتيب بيفرق في الtuples لإنهم لستة مرتبة من البيانات:
heroes === #["Wonder Woman", "Batman", "Superman"];
<< false
This media is not supported in your browser
VIEW IN TELEGRAM
Topic دسم
مش هتلاقيه كتير ، مستني إيه خش إتفرج وسيب رأيك🖤
https://youtu.be/VPHgxaOAIPo
دا كنز حرفيًا ،
دا interactive visualizer هيساعدك تفهم ال dom event systems

https://domevents.dev/
🔥1
لو هنتكلم عن الmemory management بشكل عام ف لغات البرمجة بتتقسم لشقين ، شق بيخليك إنت كمبرمج تتحكم manualluy ب إيدك وتخصص الmemory و ت free up زي ال c++ وال c عن طريق functions زي malloc و free وغيرهم وتقدر تستخدم libraries تضيف نوع من أنواع ال garbage collection زي boehm-demers-weiser ، بس دي مش جزء من اللغة نفسها ،
ولغات تانية بتعمل دا بشكل automated عن طريق الgarbage collection زي الjava و python و js ، فيه شق تالت بقي خرج برا الصندوق وفكرت بشكل مختلف زي Rust ، عملت نظام خاص بيها إسمه الownership بيطبق وقت الcompile time وبيتكون من شوية principles
زي الsingle owner وال scope و ال borrowing وال safe references ،
تعال بقي نتكلم ف حبيبتنا ،


Garbage Collection - Memory Management in Js

لو لقيت نفسك في موقف المتصفح يقفل فجأة أو ي freeze ، ممكن تتسائل إيه الأسباب اللي ورا ده. ممكن تقول السبب أخطاء في js code ، وفعلاً ده صح في أغلب الأوقات. فيه كذا طريقة js ممكن تستهلك بيها limit of a browser’s memory capacity
الحاجات دي بتتسمى memory leaks (تسريبات الذاكرة) وبتأثر بشكل كبير على تجربة المستخدم. واحدة من الطرق الشائعة اللي اللغات البرمجية بتستخدمها لمكافحة الحالة دي هي استخدام garbage collection.

ببساطة، الـ garbage collection هي نوع من automatic memory management . بتسترجع الذاكرة اللي بيشغلها الobjects اللي مبقتش مستخدمة في execution .

فهل جافاسكريبت بتستخدم garbage collection؟

أيوة، جافاسكريبت بتستخدم طريقة لgarbage collection بشكل دوري لما يبقي مفيش references للunused object or variable . العملية دي بتتم بشكل automated وبتساعد في ضمان إن المتصفح ميتحملش overload في الذاكرة ويتوقف.

العملية دي بتمشي كالتالي:

- تخصيص مساحة الذاكرة المطلوبة للبرنامج (Allocation)
- processing و execution للأكواد.
- تحرير مساحة الذاكرة من ال variables و objects اللي مبقتش مستخدمة.
علشان نعرف إيه ال variables و objects اللي محتاجة تتحذف، بيستخدموا اتنين algorithms رئيسيتين اسمهم Mark-and-sweep

الalgorithms lifecycle دي بتتكون من مرحلتين

مرحلة التعليم (Mark Phase)

المرحلة دي بت scans ال variables و objects المختلفة وبتتأكد إنها referenced من حاجة تانية في البرنامج. لو مفيش reference ، بتحذف الobject من الذاكرة.


مرحلة الكنس (Sweep Phase)

بتنضف ال heap memory من كل الobjects اللي ملهاش reference.
أي object قيمته false بيتشال من ال heap memory.

العملية دي بتحصل بشكل automated لكن ده مش معناه إن ال JavaScript developer مش لازم يقلق منها. العكس صحيح، تجاهلها ممكن يكون ضار بتنفيذ البرنامج، تعالوا نستكشف الموضوع ده أكتر.


إيه هو الـ Memory Leak في الJavaScript ؟
زي ما وضحنا دور الـ garbage collector في منع الmemory leaks ، إيه هو الـ memory leak بالتحديد؟

ببساطة، الـ memory leak هو البيانات اللي الcompiler نسي يستخدمها. ممكن نعرفها ك memory مبقتش مطلوبة لتنفيذ برنامجك لكنها محصلهاش released عشات ت free up ال memory capacity.

لما بتcreate ال objects وvariables ، الcompiler بيستهلك بعض من الmemory علشان يتابع المعلومات دي.
الـ garbage collector بيكون عنده القدرة إنه يعرف امتى المتغير مبقاش مطلوب لتنفيذ البرنامج.

الـ memory leak بيحصل لما البرنامج ميعدش محتاج المتغير اللي اتعمل، لكن run time environment (المتصفح) بتعتقد إنك لسه محتاجه. ده بيسبب تعارض بين بيئة التشغيل وتنفيذ الكود. مقارنةً بخطأ typical runtime error ، الـ memory leak غالبًا مش بتظهر في شكل خطأ واضح. وده لأنهم مش بينتجوا عن كود مش valid بشكل صريح، لكن من عيب منطقي في الstructure للكود.
في النهاية، ده بيسبب بطء في أداء التطبيق وغالبًا بيوصل لتعطل أو تهنيج المتصفح بالكامل.
بعض السيناريوهات الشائعة اللي بتسبب الـ memory leak في الJavaScript واللي لازم تتجنبها كdeveloper
Infinite Loops
يمكن تكون أشهر سبب لmemory leaks ، الinfinite loops بتسبب تعطل المتصفح خلال تفاعل المستخدم. جرب تحط الكود ده في ال developer console debugging tools
while (true) {
//your code
}

تنفيذ الكود ده هيخلي المتصفح يهنج. لكن الكود ده معمول علشان يسبب تmemory leak ومش العادي إنك تلاقيه في production code . الغالب إن تايمر منسي يخلق السيناريو ده واستخدام setInterval غالبًا ورا الحالات دي.
خد التايمر ده كمثال:
var counter = 10;
setInterval(function(){
console.log(counter);
counter--;
if (counter === 0) {
console.log("I am running!");
}
}, 1000);

من الوهلة الأولى، ممكن تفترض إن الloop دي هتتوقف بعد 10 مرات. لكن setInterval مش بيعمل غير إنه يمرر function محددة. بنفسه، مفيش stop أو break ! ، والموضوع ده ممكن يتنسى.

لما نستخدم clearInterval، نقدر نوقف التايمر . بياخد بارامتر واحد بيحدد ال function المحددة اللي عايز توقفها.
var counter = 10;
var runningFunction = setInterval(function(){
console.log(counter);
counter--;
if (counter === 0) {
console.log("I am running!");
clearInterval(runningFunction);
}
}, 1000);

إضافة clearInterval لما بنستخدم setInterval ممكن تمنع memory leaks غير الضرورية في كودك.

الـ Closures
زي ما ممكن تكون عارف، الـ closures هي ركن أساسي من أساسيات جافاسكريبت. الـ closures بتتسمى كتير function بترجع function . الفكرة الرئيسية إن ال inner function عندها access لمتغيرات ال
outer functions
خلينا نبين ده بمثال:


function buildName(name) {
var greeting = "Hello, " + name + "!";
var sayHello = function() {
var welcome = greeting + " Welcome!";
console.log(greeting);
};
return sayHello;
}


ده مثال بسيط لعمل closure
buildName بيعمل متغير في local scope بتاعه
sayHello موجودة ك function في الinner scope (جوا sayHello).
sayHello لسه عندها access لمتغير greeting حتى لو اتعمل في scope مختلف.
الـ closures فعالة جدًا لما بتحاول تكتب كود يكون تكراري وكذلك الكود اللي مش بيكرر نفسه.

إزاي الـ closures ممكن تسبب memory leak ؟
الـ memory leak بيحصل في الـ closure لو واحد من المتغيرات اللي حصلها declared في الouter function بقت متاحة للinner nested function.
ال reference ده لازم يفضل موجود في الذاكرة علشان ال inner nested function توصل للمتغيرات دي. عشان كده، المتغيرات دي مش هتتحذف بالـ garbage collector وده ممكن يسبب memory leak .

الglobal variables الغير مقصودة (Accidental )
من السهل الوقوع في فخ ال memory leak بسبب وجود global variables في الكود.

هنا مثال على إنشاء global variables:
var createdVariable = "This is a global variable";

function myFunction() {
// المتغير createdVariable متاح هنا جوا myFunction()
}


أي متغير اتعمل في الtop scope level of the document بيبقى global.

في المثال ده، createdVariable اتعمل برا الscope بتاع myFunction، ومن ثم مفيش local scopes تانية، globalVariable بيعيش في الtop level.

الGlobal variables مش بتتحذف بالـ garbage collector. لازم ناخد الحذر دايمًا لما نستخدم الGlobal variables في كودنا.

فكر في window object في المتصفح، ده في الأساس highest tier of scope اللي الjs بتعيش فيه.

ممكن تجرب ده بفتح ال dev tools وكتابة this في console.

ال window object بيرجع لنا هنا، بيبين إن current scope هو global scope.

أي متغيرات معلنة بشكل global ممكن تعملها access من كل الscripts والlibraries والfunctions في JavaScript document . وده واحد من الأسباب الرئيسية ليه مش بيتجمع بالـ garbage collector.
ألحل العملي بقي عشان أقلل من ال Global variables
استخدام use strict
تعتمد ع ال Block scope إستخدام let بدل var
👍2
النهارده كنت محتاج أكتشف إذا كان المستخدم مشغل adblocker ولا لأ. ممكن تسأل ليه؟ في الحالة دي، كنت عاوز أتحقق من بعض بيانات المستخدم عن طريق نظام خارجي، لكن الـ adblockers زي Ghostery هتمنع الاتصال دا. مثال ع المواقع العالمية اللي بتستخدم اتصالات بأنظمة خارجية هو موقع Facebook اللي بيتتبع تفاعل المستخدمين عن طريق Google Analytics. لو كان المستخدم مشغل adblocker، الطلبات دي ممكن تتمنع.
عشان كده، جربت أدور كتير عشان ألاقي طرق لاكتشاف الـ adblockers.
الطريقة الأولى اللي استخدمتها هي JavaScript onError Callback. بنضيف سكريبت وهمي في الـ HTML، والـ adblocker هيمنعه. لو السكريبت اتمنع، الfunction بتاعتنا هتشتغل.
<script
async
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
onerror="adBlockFunction();"
></script>
الfunction اللي بتشتغل لما السكريبت يتمنع:


const adblocker = document.getElementById('adblock-message');
adblocker.style.display = 'block';
وفي الـ HTML بنضيف ديف مخفي يظهر الرسالة لو تم اكتشاف الـ adblocker.

<div id="adblock-message" class="hidden">Sorry, you have your adblocker on!</div>


الطريقة الثانية: JavaScript File Check
هي إننا نعرف سكريبت JavaScript زي كده:

<script src="/js/ads.js"></script>
جوا الملف دا نكتب:


var canRunAds = true;


ونستخدم الكود دا عشان نتحقق:



if (window.canRunAds === undefined) {
const adblocker = document.getElementById('adblock-message');
adblocker.style.display = 'block';
}



الطريقة الثالثة: استخدام div ثابت
طريقة تالتة هي إنك تستخدم "ad" ثابت في الـ HTML:


<div
id="detect"
class="ads ad adsbox doubleclick ad-placement carbon-ads"
style="background-color:red;height:300px;width:300px;position: absolute;left:0;top:0;"
>
 
</div>
وبعدين نتحقق من الارتفاع:


const testAd = document.getElementById('detect');
window.setTimeout(function() {
if (testAd.offsetHeight === 0) {
const adblocker = document.getElementById('adblock-message');
adblocker.style.display = 'block';
}
testAd.remove();
}, 100);
كل الطرق دي مفيدة، بس لازم تجربها على كذا متصفح وكذا نوع من الـ adblockers عشان تتأكد إنها بتشتغل في كل الحالات.
1
هتكلم عن حاجة مش واخدة حقها في ال js وناس كتير متعرفهاش وهي ال MutationObserver
الـ MutationObserver بيتيح لك تراقب التغييرات اللي بتحصل في DOM بتاعك بشكل فعال وسريع
يعني إيه MutationObserver؟
MutationObserver هي API موجودة في JavaScript بتسمح لك تراقب أي تغيير بيحصل في DOM nodes. يعني لو حصل إضافة، حذف، أو تعديل لأي عنصر في الصفحة، الـ MutationObserver هيقدر يكتشف دا.
استخداماته
مراقبة تغييرات في الـ DOM: زي ما قولنا، لو فيه تغيير في أي عنصر في الصفحة، تقدر تعرف وتتصرف بناءً عليه.
تحديث الـ UI تلقائياً: لو عندك عناصر في الصفحة بتتغير كتير، ممكن تستخدم الـ MutationObserver عشان تعمل تحديث تلقائي للـ UI.
إزاي تستخدم الـ MutationObserver؟
في البداية، بنعرف الـ MutationObserver نفسه. الـ MutationObserver بياخد callback function ك Argument . الـ callback دي هي اللي بتتنفذ كل ما يحصل تغيير في الـ DOM.
const observer = new MutationObserver((mutationsList, observer) => {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
console.log('A child node has been added or removed.');
} else if (mutation.type === 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.');
}
}
});
تاني حاجة ال callback function
الـ callback function اللي بنمررها للـ MutationObserver بتاخد 2 Arguments
mutationsList: قائمة بكل التغييرات اللي حصلت.
observer: الـ observer نفسه اللي بيتنفذ الكود من خلاله.
تالت حاجة التعامل مع التغييرات
بنستخدم for...of loop عشان نمر على كل التغييرات اللي في mutationsList ونتعامل معاها بناءً على نوع التغيير
childList: لو التغيير في الأطفال (إضافة أو حذف عناصر).
attributes: لو التغيير في خصائص العنصر (زي تعديل خاصية معينة).
رابع حاجة وهي تحديد العنصر والإعدادات
دلوقتي بنحدد العنصر اللي عايزين نراقبه والإعدادات اللي عايزين نتابعها. بنستخدم observe method للـ observer عشان نبدأ المراقبة.
const config = { attributes: true, childList: true, subtree: true };
const targetNode = document.getElementById('some-id');
observer.observe(targetNode, config);
المعاملات بتاعت observe:
targetNode: العنصر اللي عايزين نراقبه.
config: إعدادات المراقبة، ودي عبارة عن object بيحدد نوع التغييرات اللي عايزين نتابعها:
attributes: لو عايزين نتابع التغييرات في خصائص العنصر.
childList: لو عايزين نتابع التغييرات في الأطفال (إضافة أو حذف عناصر).
subtree: لو عايزين نتابع التغييرات في كل الnodes اللي تحت العنصر ده.
خامس حاجة إيقاف المراقبة
لو حبينا نوقف المراقبة في أي وقت، بنستخدم disconnect method للـ observer.
observer.disconnect();
دي مهمة عشان ال memory leaks اللي إتكلمنا عليها قبل كدا !
إمتي أستخدمه والأمثلة اللي بي shine فيها ؟
لو عايز تراقب متى يتم إضافة أو إزالة عناصر في الـ DOM. دا مفيد لما يكون عندك محتوى بيتحدث ديناميكياً بناءً على تفاعل المستخدم أو بيانات جديدة.
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.addedNodes.length > 0) {
console.log('Element added:', mutation.addedNodes[0]);
}
if (mutation.removedNodes.length > 0) {
console.log('Element removed:', mutation.removedNodes[0]);
}
});
});
لو عايز تراقب متى يتغير أي attribute في عنصر معين. دا مفيد لو عايز تتبع تغييرات معينة زي تغيير الـ class أو الـ style.
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes') {
console.log('Attribute changed:', mutation.attributeName);
}
});
});
لو عايز تراقب متى يتغير النص داخل عنصر معين. دا مفيد لو عندك محتوى بيتم تحديثه ديناميكياً وعايز تتأكد من تحديثه بشكل صحيح.

const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'characterData') {
console.log('Text changed:', mutation.target.data);
}
});
});

MutationObserver
بيكون أداة قوية ومهمة لما تحتاج تتبع التغييرات بدقة وكفاءة في الـ DOM، بس في نفس الوقت، ما بيستخدمش لما تكون التغييرات ممكن تتبعها بأحداث بسيطة زي scroll أو click أو input.