إيه الجديد في JavaScript
متستغربش :( إنت بتكبر وال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
onst 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!!!
تالت حاجة هي 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"]
بعد ما تعمل الTuple ده، مش ممكن تضيف قيم تانية أو تشيل قيم. القيم نفسها كمان مش ممكن تتغير.
ال (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
تقدر تجرب الtuples and records هنا