نصائح وحيل لتحسين طريقة كتابتك لـ JavaScript.
صورة من Aarohi Achwal عبر Parenting Firstcry
ما هو Falsy؟
ببساطة، هي أي قيمة تُقيَّم كـ false أو قابلة للإلغاء (nullable) أو فارغة.
- False => Falsy
- Null => Falsy
- Undefined => Falsy
- سلسلة نصية فارغة => Falsy
- مصفوفة بلا عناصر => Falsy
- كائن بلا مفاتيح (Object.keys(obj).length === 0) => Falsy
- صفر => Falsy
هذا يعني أنه إذا كان لديك متغيّر:
const name = '';وشرط تريد فيه فحص المتغيّر:
if (CHECK IF NAME IS EMPTY) {
throw new Error('Missing name');
}فأنت لست بحاجة لمقارنته بسلسلة نصية فارغة أو null أو undefined:
// Unnecessary
if (name === '' || name === undefined || name === null) { ... }أو تحويله إلى قيمة منطقية (boolean) للتحقق مما إذا كان Falsy (كما تفعل في لغات أخرى ذات كتابة صارمة). بدلًا من ذلك، اعتبرها قيمة Falsy (مثل قيمة منطقية) وضع فقط بادئة ! وستُقيّمها JavaScript نيابة عنك:
// Simpler
if (!name) {
throw new Error('Missing name');
}ما هو Truthy؟ حسنًا، إنه عكس Falsy:
- True
- رقم أكبر أو أصغر من الصفر
- سلسلة نصية بحرف واحد على الأقل
- مصفوفة أو كائن بعنصر واحد على الأقل
- متغيّر له قيمة، مثل ('A'، 1، {}، [])
تنوّع النتائج
// name = '';
!name === !false // True
// name = undefined;
!name === !false // True
// name = null;
!name === !false // True
// name = [];
!name.length === !false // True
// name = 0
!name === !false // Trueوبالمثل، إذا كانت النتيجة معاكسة، ستُقيَّم كقيمة Truthy.
// sport = 'Football';
!sport === !true // True
// sport = ' ';
!sport === !true // True
// sport = ['Football'];
!sport.length === !true // True
// sport = 1
!sport === !true // True
من الطرق الشائعة للتبديل بين قيم truthy وfalsy استخدام المعاملات المنطقية:
- And (&&)
- Or (||)
&&
عند إعداد شرط بين قيمتين، سيلتقط معامل && القيمة التي تُقيَّم كـ False.
إذا كانت أي من القيمتين في الشرط Falsy، ستكون النتيجة false:
true && false // False
false && true // False
false && false // Falseفقط إذا كانت كلتا القيمتين Truthy، سيُقيَّم معامل && كـ true:
true && true // Trueضع في اعتبارك أن && ستُقيّم جميع القيم في الشرط حتى تجد أول قيمة Falsy. وإلا، ستأخذ آخر قيمة.
true && 'Hello' && 100; // 100 (Truthy value) التحقق من إدخال المستخدم
إذا فشل أي شرط، ستُقيَّم العبارة كـ False.
const email = 'hello';
if (email.includes('@') && email.includes('.com') {
console.log('Email is valid!');
} else {
console.log('Email is invalid!');
} عرض المحتوى الديناميكي
في أطر عمل الويب مثل React، يمكنك عرض عناصر HTML (أو مكونات) فقط عند تحقق شرط معين.
<div>
{ conditionIsMet && <h1>Hello World</h1> }
</div> تجنّب القيم القابلة للإلغاء
من الأخطاء الشائعة التي يرتكبها المطورون محاولة قراءة قيمة من خاصية يكون أصلها (parent) بقيمة null أو undefined.
const array = [];
console.log(array.length); ✔️
const newArray = null;
console.log(newArray.length); ❌ // Exceptionلحل هذا، تأكد أولًا أن الخاصية الجذر ليست null أو undefined، ثم حاول قراءة محتوى الخاصية المطلوبة.
if (newArray !== null && newArray.length === 0) {
console.log('newArray is empty!');
} ||
يعمل معامل الـ OR المنطقي (||) بشكل معاكس لمعامل &&. فهو يبحث عن أي قيمة في الشرط تُقيَّم كـ Truthy ويأخذ تلك القيمة.
true || true // True
true || false // True
false || true // Trueفقط إذا كانت كلتا القيمتين Falsy، ستكون النتيجة false:
false || false // Falseستُقيّم || جميع القيم في الشرط حتى تجد أول قيمة Truthy. وإلا، ستأخذ آخر قيمة.
false || undefined || null // Null البحث ضمن مجموعة من العناصر
يمكن استخدام معامل || لتصفية العناصر التي تحقق شرطًا أو آخر.
const clothes = [
{
type: 'Shirt',
color: 'Black',
size: 'XL',
price: 0
},
{
type: 'Shirt',
color: 'White',
size: 'XL',
price: 100
},
{
type: 'Skirt',
color: 'Red',
size: 'L',
price: 50
}
];
const favClothes = clothes
.filter(item => item.color === 'Black' || item.color === 'White');
console.log('favClothes :>> ', favClothes);
/*
[
{ type: 'Shirt', color: 'Black', size: 'XL' },
{ type: 'Shirt', color: 'White', size: 'XL' }
]
*/ تعيين قيم افتراضية
إذا كانت إحدى العبارات Falsy، يمكنك استخدام معامل || لإعداد قيمة افتراضية:
function findHero(hero) {
const defaultHero = 'Goku';
const myHero = hero || defaultHero;
return heroes.find(h => h.name === myHero);
} معاملات متعددة
عندما يكون لديك عدة معاملات && و|| في عبارة واحدة، تُطبَّق قاعدة الأسبقية. سيُقيَّم أول شرطين، ثم تُقيَّم نتيجتهما مقابل القيمة الثالثة:
console.log(true && null || false ); // False
// #1 true && null (where null is Falsy) === Null
// #2 null || false === Falseconsole.log(false || 100 && undefined ); // Undefined
// #1 false || 100 (where 100 is Truthy) === 100
// #2 100 && undefined (truthy && falsy) === Undefinedconsole.log(null || 0 && '' || true); // True
console.log(null || 0 && '' && false); // 0
أدخل ES2020 معاملًا جديدًا، الدمج اللاإلغائي (Nullish Coalescing)، المعروف أيضًا باسم Elvis operator.
const possiblyNull = null;
const result = possiblyNull ?? 'Default Value';
console.log(result); // 'Default Value'const possiblyUndefined = undefined;
const result = possiblyUndefined ?? 'Default Value';
console.log(result); // 'Default Value'يعمل بشكل مشابه لمعامل ||. لكن بينما يُطبَّق || على جميع قيم falsy، يقتصر معامل الدمج اللاإلغائي فقط على قيم null وundefined.
إذا استُخدم مع أنواع أخرى، فسيعيد ببساطة القيمة الأولى:
false ?? true // False
true ?? false // True
طريقة أخرى لتجنّب الخصائص القابلة للإلغاء هي استخدام معامل التسلسل الاختياري (Optional Chaining).
بدلًا من تكرار نفسك:
if (newArray !== null && newArray.length === 0) {
console.log('newArray is empty!');
}يمكنك تطبيق التسلسل الاختياري:
if (newArray?.length === 0) {
console.log('newArray is empty!');
}ما سيفعله هذا هو:
إذا كان الأمر كذلك، سيُقيَّم الشرط كـ null/false ما يُنهي العبارة (ينتقل إلى حالة else).
- يقيّم ما إذا كانت newArray قابلة للإلغاء
- يتحقق من طول newArray (بعد تقييم newArray بالفعل)
وهذا أنظف بكثير. كما يعمل مع أي عدد من الخصائص لديك:
const name = currentUser?.username?.name?.firstName;يمكنك أيضًا الجمع بين التسلسل الاختياري ومعاملات أخرى:
const name = user?.username ?? 'Default Username';
console.log(name);ستُطبع 'Default Username' إذا:
- كان user قيمته null أو undefined
- كان user.username قيمته null أو undefined
بدلًا من ذلك، إذا افترضنا أن خاصية user معرَّفة بالفعل (لها قيمة)، يمكنك تعيين قيمة افتراضية لـ user.username باستخدام تفكيك الكائن (Object Destructuring):
const { username = 'Default Username' } = user;
console.log(name);حيث ستساوي username 'Default Username' فقط إذا كانت undefined أو null.
طريقة شائعة ومباشرة للتبديل بين قيم truthy وfalsy هي استخدام المعامل الثلاثي (Ternary Operator). يعمل كالتالي:
- إذا تحقق الشرط كـ true (أ)
- ستكون النتيجة الخيار الأول (ب)
- وإلا، ستكون النتيجة الخيار الآخر (ج)
const isGreaterThan = 10 > 1 ? true : false;
console.log(isGreaterThan); // True
//
const isLesserThan = 10 < 1 ? true : false;
console.log(isLesserThan); // False
أحدث إضافة إلى JavaScript هي مجموعة من معاملات الإسناد المنطقي (Logical Assignment). فكّر في كل ما تعلمته حتى الآن مجتمعًا مع القدرة على إسناد القيم أثناء التنفيذ.
فبدلًا من:
function setHero(myHero) {
myHero = myHero ?? 'Goku';
return myHero;
}
const result = setHero();
console.log(result) // 'Goku'ستفعل:
function setHero(myHero) {
myHero ??= 'Goku';
return myHero;
}
const result = setHero();
console.log(result) // 'Goku'الدافع وراء هذا هو تقليل الخطوة الإضافية اللازمة للتحقق من القيم ثم إسنادها. الآن يحدث كل ذلك دفعة واحدة.
بالنسبة للسيناريوهات الأخرى من نوع Falsy، يمكنك استخدام معامل || المعتاد:
function setSalary(mySalary) {
const minimum_salary = 1000;
mySalary ||= minimum_salary;
return mySalary;
}
const result = setSalary();
console.log(result) // 1000هذا ينطبق أيضًا على سيناريوهات أكثر تعقيدًا:
const cybertruck = {
topSpeedInKmh: 180,
maximumBatteryLife: null,
towingCapacity: undefined
};
const defaultTopSpeed = 100;
const defaultBatteryCapacity = '122.4 kWh'
const defaultTowingCapacity = '11 000 pounds'
cybertruck.topSpeedInKmh ||= defaultMaxSpeed; // takes first truthy value
cybertruck.maximumBatteryLife ??= defaultBatteryCapacity; // avoids null
cybertruck.towingCapacity &&= defaultTowingCapacity; // takes falsy value
console.log(cybertruck.topSpeedInKmh); // 180
console.log(cybertruck.maximumBatteryLife); // '122.4 kWh'
console.log(cybertruck.towingCapacity); // undefined
التقييم الضمني
إذا كانت القيمة تُقيَّم كـ truthy أو falsy، فلست بحاجة للتصريح صراحة بأن النتيجة true أو false.
# صريح
if (value === true) { ... } # ضمني
if (value) { ... } # صريح
const isGreaterThan = 10 > 1 ? true : false; # ضمني
const isGreaterThan = 10 > 1; # صريح
const freeItem = clothes.find(item => item.price === 0); # ضمني
const freeItem = clothes.find(item => !item.price);
// { type: 'Shirt', color: 'Black', size: 'XL', price: 0 } التحويل إلى Boolean
يمكنك أيضًا تحويل قيمة صراحةً إلى قيمة منطقية (boolean) باستخدام زوج من علامات التعجب.
const greeting = 'Hello';
const truthy = !!greeting; // Trueconst empty = '';
const falsy = !!empty; // Falseبدلًا من ذلك، يمكنك استخدام دالة البناء Boolean():
const greeting = 'Hello';
const empty = '';
console.log(Boolean(greeting)); // True
console.log(Boolean(empty)); // False