ES6 وهى اختصار ل (ECMAScript 2015) و هي النسخة السادسة من مواصفات لغة JavaScript.
أدخلت العديد من الميزات الجديدة وتحسينات على كود لغة JavaScript، بما في ذلك:
محتوي المقال
إستخدام كلمة let و const
let
و const
هما كلمتان يستخدمان لإنشاء متغيرات في JavaScript.
تستخدم let
لإنشاء متغيرات يمكن تغيير قيمتها بينما يتم استخدام const
لإنشاء متغيرات ثابتة لا يمكن تغيير قيمتها بعد إعطاءها قيمة.
على سبيل المثال، يمكن استخدام let
لإنشاء متغير يحتوي على عدد، ويمكن تغيير قيمته كالتالي:
let x = 5; x = 10; // قيمة x الجديدة هي 10
بينما يمكن استخدام const
لإنشاء ثابت يحتوي على قيمة لا يمكن تغييرها، كما في المثال التالي:
const pi = 3.14159; pi = 3; //سيحدث خطأ.
يرجى ملاحظة أنه عند استخدام const
لإنشاء متغير، يجب تعيين قيمته في نفس الوقت الذي تتم فيه إنشاء المتغير.
وبالنسبة للكلمة let لعلك تتسأل ما الفرق بينها اذًا وبين الكلمة var التى تستخدم لإنشاء المتغيرات فى الإصدار السابق.
الفرق الرئيسي بين let
و var
في JavaScript هو كيفية تعاملهما مع نطاق المتغيرات أو الـ Scope.
عند استخدام var
لإنشاء متغير، يتم إنشاؤه داخل النطاق الذي تم إنشاؤه فيه ويكون متاحًا في النطاق العام (global scope) إذا تم إنشاؤه في المستوى الأعلى من البرنامج.
على النقيض، فإن let
يعمل في النطاق الذي يتم إنشاؤه فيه (Block scope)، مما يعني أن المتغير الذي تم إنشاؤه بـ let
يكون محدودًا داخل الكتلة المحيطة به (block)، سواء كانت داخل دالة، حلقة (loop)، أو أي بناء برمجي آخر.
هذا يعني أنه إذا تم إنشاء متغير باستخدام var
داخل دالة، فسيكون متاحًا في النطاق العام. في حين أن المتغير الذي تم إنشاؤه باستخدام let
داخل نفس الدالة، سيكون محدودًا داخلها فقط ولن يكون متاحًا في النطاق العام (اي خارج الدالة).
هناك أيضًا بعض الاختلافات الأخرى بين let
و var
، مثل تمكين let
من تعيين قيمة افتراضية للمتغيرات، ولكن لا يتم ذلك مع var
، وكذلك ستعطي let
خطأ عند محاولة إعادة تعريف المتغير في نفس النطاق، بينما يمكن القيام بذلك بدون أي خطأ باستخدام var
.
function exampleFunction() { var x = 1; let y = 2; if (true) { var x = 3; let y = 4; console.log(x); // Output: 3 console.log(y); // Output: 4 } console.log(x); // Output: 3 console.log(y); // Output: 2 } exampleFunction();
لاحظ فى المثال السابق قمنا بتعريف المتغيرين x , y بطرقتين مختلفين عن طريق var و let لاحظ الفرق بينهم.
بالنسبة ل let y داخل نطاق الدالة تكون قيمته 2 ام داخل نطاق if يكون قيمته 4.
فى حين var x دخل نطاقة الدالة تتغير قميته من 1 إلى 3 ويكون قيمة الطباعة دائمًا 3.
الدوال السهمية Arrow Functions
الدوال السهمية او Arrow Functions هي طريقة جديدة لتعريف الدوال في ES6 وتمثل طريقة مختصرة لتعريف الدوال المجهولة (anonymous functions). وتسمح الـ Arrow Functions بتحسين واضح لشكل الكود وتبسيطه أكثر من الطرق الإعتيادية.
وهناك بعض الفروق الأساسية بين Arrow Functions والدوال التقليدية:
- لا يوجد الحاجة لاستخدام كلمة function فى الدوال السهمية
- يتم تحديد المعاملات او الباراميترات بين الأقواس ()
- يمكن الإستغناء عن الأقواس () فى حالة وجود معامل واحد فقط
- إذا كان لدينا سطر واحد فقط في الدالة، يمكن تجاهل الأقواس {}
- لا تحتوي الدوال السهمية Arrow Functions على سياق (context) خاصة بها، ولذلك فإن إستخدام this يشير إلى الكائن الأب الذي يحتوي علي الدالة السهمية.
وهنا مثال يوضح استخدام الـ Arrow Functions:
const add = (a, b) => { return a + b; }; console.log(add(2, 3)); // يطبع: 5
وهذا الشكل الأبسط فى حالة إستخدام سطر واحد فقط فى جسم الدالة.
const multiply = (a, b) => a * b; console.log(multiply(2, 3)); // يطبع: 6
وهذا شكل مبسط أكثر فى حالة إستخدام معامل واحد فقط حيث يمكن الأستغناء عن ()
let bob = a => a + 100;
معامل الإنتشار …
معامل النشر أو Spread Operator هو عبارة عن ثلاث نقاط (…)، ويستخدم في ES6 لتحويل عنصر أو مصفوفة إلى قائمة من العناصر.
ويمكن استخدام معامل النشر في العديد من الأماكن، على سبيل المثال:
- نسخ قيمة مصفوفة إلى مصفوفة أخرى
- إرجاع قائمة جديدة بعد إضافة عناصر إلى مصفوفة موجودة بالفعل
- تمرير عدد غير محدد من المعاملات إلى دالة
نسخ قيمة مصفوفة إلى مصفوفة أخرى
const arr1 = [1, 2, 3]; const arr2 = [...arr1]; // نسخ محتوى arr1 إلى arr2
إرجاع قائمة جديدة بعد إضافة عناصر إلى مصفوفة موجودة
const arr1 = [1, 2, 3]; const arr2 = [...arr1, 4, 5, 6]; // إضافة 4، 5، 6 إلى arr1
تمرير عدد غير محدود من الباراميترات إلى دالة
const sum = (...args) => { return args.reduce((total, current) => total + current, 0); } console.log(sum(1, 2, 3)); // Output: 6
الجملة التكرارية For/Of
الجملة التكرارية For/Of هي ميزة جديدة في ES6 تستخدم للتكرار عبر عناصر مصفوفة أو أي كائن قابل للتكرار.
لمثال على استخدام الجملة التكرارية For/Of، يمكننا التكرار عبر العناصر في مصفوفة باستخدام الشكل التالي:
const cars = ["BMW", "Volvo", "Mini"]; let text = ""; for (let x of cars) { text += x + " "; }
الفئات او Classes
تم إضافة دعم كامل للبرمجة الشيئية او OOP فى جافاسكربت ES6.
يسمح لنا استخدام الفئات او Classes بتعريف مواصفات وخصائص لكائن معين، ويمكن إنشاء كائنات جديدة باستخدام هذه المواصفات. وبهذا يسهل علينا إنشاء عدد كبير من الكائنات المتشابهة بسهولة، بدلاً من إعادة كتابة الشفرة المصدرية الخاصة بالكائنات المشابهة مرارًا وتكرارًا.
class Person { constructor(name, age) { this.name = name; this.age = age; } sayHello() { console.log(`مرحبًا اسمى هو ${this.name} و انا عمرى ${this.age} سنة.`); } } const person1 = new Person('John', 25); person1.sayHello(); // Hello, my name is John and I'm 25 years old.
في هذا المثال، تم إنشاء فئة جديدة تسمى “Person” والتي تحتوي على خصائص “name” و “age”، والدالة “sayHello” التى تعرض رسالة ترحيبية تحتوي على اسم الشخص وعمره. ثم تم إنشاء كائن جديد باستخدام الفئة “Person”، والذي يتم تمرير اسم وعمر الشخص عند الإنشاء، ثم استخدام طريق الـ “sayHello” لعرض رسالة (لاحظ أنه يمكن إنشاء عدد لا نهائى من الكائنات من نفس الفنئة بتمرير الاسم والعمر).
الوعود او Promises
Promises هي ميزة أضيفت في ES6 والتي تساعد في إدارة العمليات القائمة على الشبكة والتى تستغرق وقت فى العادة ولاتحدث لحظيًًا (مثل الاسترجاع من قاعدة البيانات أو الحصول على بيانات عبر API). تستخدم Promises لتمثيل عملية غير متزامنة (Asynchronous) التي قد تستغرق بعض الوقت للانتهاء.
تعد Promises بمثابة وعود (Promises) بأنها ستعود بنتيجة ما بعد استكمال العملية القائمة على الشبكة، بدلاً من تعليق تطبيق الويب أثناء انتظار الرد من الخادم.
وتتكون Promises من ثلاثة حالات ممكنة:
- Pending: في حالة عدم الإنجاز بعد.
- Resolved: في حالة الإنجاز بنجاح.
- Rejected: في حالة عدم الإنجاز بسبب وجود خطأ.
وفيما يلي مثال بسيط على استخدام Promises:
const promise = new Promise((resolve, reject) => { setTimeout(() => { const randomNumber = Math.random(); if (randomNumber > 0.5) { resolve('Success!'); } else { reject('Failed!'); } }, 1000); }); promise.then((result) => { console.log(result); }).catch((error) => { console.log(error); });
في هذا المثال، تم إنشاء Promise جديد والذي يعيد نتيجة عشوائية (نجاح أو فشل) بعد ثانية واحدة. ثم تم استخدام الطريقتين then
و catch
للتعامل مع نتيجة الـ Promise. وإذا تم إرجاع نتيجة ناجحة من الـ Promise، فإن الطريقة then
ستعمل، أما إذا تم إرجاع نتيجة فاشلة فإن الطريقة catch
ستعمل.
المعاملات الافتراضية أو Default parameters
تسمح المعاملات الإفتراضية للمطورين بتعريف قيمة افتراضية للمعاملات Parameters في الدالة. وبهذه الطريقة، يمكن تجنب الحاجة إلى تعيين القيم الافتراضية بشكل يدوي فى إستدعاء الدالة.
فيما يلي مثال بسيط يوضح استخدام المعاملات الافتراضية:
function greet(name = 'Guest') { console.log(`Hello, ${name}!`); } greet(); // يطبع "Hello, Guest!" greet('Ahmed'); // يطبع "Hello, Ahmed!"
فى المثال السابق عند إستدعاء الدالة بدون تمرير المعامل name ستقوم الدالة بطريقة إفتراضية بتعيين القيمة Guest بينما تأخذ القيمة عند تمريرها.
الوحدات أو Modules
تتيح ميزة الوحدات (Modules) فى ES6 إمكانية تقسيم الكود إلى ملفات منفصلة ومنظمة، حيث يمكن لكل ملف أن يحتوي على دوال ومتغيرات خاصة به ويتم استدعاءها عند الحاجة.
بشكل عام، يتم تصدير المتغيرات والدوال في ملف الوحدة باستخدام الكلمة الرئيسية export
، ويتم استيرادها في ملف آخر باستخدام الكلمة الرئيسية import
. وبهذه الطريقة، يمكن استخدام المتغيرات والدوال المصدرة من ملف آخر دون الحاجة إلى إعادة كتابتها من جديد.
فيما يلي مثال بسيط يوضح استخدام الوحدات:
الملف الاول file1.js
const message = "Hello, World!"; function showMessage() { console.log(message); } export { message, showMessage };
الملف الثانى file2.js
import { message, showMessage } from './file1.js'; console.log(message); // يطبع "Hello, World!" showMessage(); // يطبع "Hello, World!"
في هذا المثال، تم تصدير المتغير message
والدالة showMessage
في ملف file1.js
باستخدام الكلمة الرئيسية export
، وتم استيرادهما في ملف file2.js
باستخدام الكلمة الرئيسية import
.
وتساعد ميزة الوحدات على تنظيم الكود وجعله أكثر قابلية لإعادة الاستخدام، كما تحافظ على عزل الكود وتجعله أكثر أماناً وأقل عرضة للأخطاء.
العمليات على النصوص
تتضمن ميزات ES6 العديد من العمليات المفيدة على النصوص (Strings)، من بينها:
String.includes()
هي دالة جديدة تستخدم للبحث عن وجود نص محدد داخل نص آخر. تعمل الوظيفة على إرجاع قيمة true
إذا وجد النص المحدد و false
إذا لم يتم العثور عليه.
const str = 'مرحبا بكم في موقعنا'; console.log(str.includes('مرحبا')); // true console.log(str.includes('أهلا')); // false
String.startsWith()
هي دالة وتستخدم للتحقق مما إذا كانت السلسلة النصية تبدأ بنص محدد أم لا. وتقوم هذه الوظيفة بإرجاع قيمة منطقية true
إذا بدأ النص بالنص المحدد و false
إذا لم يبدأ.
const str = 'Hello, world!'; console.log(str.startsWith('Hello')); // true console.log(str.startsWith('world')); // false
String.endsWith()
هي دالة تستخدم للتحقق مما إذا كانت السلسلة النصية تنتهي بنص محدد أم لا. وتقوم هذه الوظيفة بإرجاع قيمة منطقية true
إذا انتهى النص بالنص المحدد و false
إذا لم ينته.
const str = 'Hello, world!'; console.log(str.endsWith('world!')); // true console.log(str.endsWith('Hello')); // false
العمليات على المصفوفات
ES6 أضافت العديد من الميزات الجديدة لعمليات المصفوفات، ومنها:
1- دالة Array.find()
تستخدم للعثور على أول عنصر يطابق شرط معين وتعيد القيمة المطابقة أو undefined
إذا لم يتم العثور على عنصر يطابق الشرط.
على سبيل المثال، للعثور على أول عنصر في المصفوفة الذي يحتوي على القيمة “apple”:
javascriptCopy codeconst fruits = ["banana", "orange", "apple", "kiwi"]; const foundFruit = fruits.find(fruit => fruit === "apple"); console.log(foundFruit); // "apple"
2- دالة Array.findIndex()
تستخدم للعثور على موضع أول عنصر يطابق شرط معين وتعيد الفهرس أو -1 إذا لم يتم العثور على عنصر يطابق الشرط.
على سبيل المثال، للعثور على الفهرس الأول في المصفوفة الذي يحتوي على القيمة “apple”:
javascriptCopy codeconst fruits = ["banana", "orange", "apple", "kiwi"]; const foundIndex = fruits.findIndex(fruit => fruit === "apple"); console.log(foundIndex); // 2
const numbers = [4, 9, 16, 25, 29]; let first = numbers.find(myFunction); function myFunction(value, index, array) { return value > 18; }
مثال أخر لإجاد اول عنصر فى المصفوفة يحقق الشرط وهو اي قيمة العنصر اكبر من 18.
لاحظ ان الدالة الممررة إلى find او findIndex يمكن أن تحتوي على ثلاثة معاملات وهما:
- قيمة العنصر
- فهرس العنصر
- المصفوفة نفسها
3. دالةArray.from()
تستخدم لإنشاء مصفوفة جديدة من أي كائن يحتوي على خاصية length ويحتوي على مجموعة من العناصر.
يمكن أن يكون هذا الكائن مصفوفة أو سلسلة نصية أو مجموعة أو حتى كائن آخر.
const str = 'hello'; const arr = Array.from(str); console.log(arr); // ['h', 'e', 'l', 'l', 'o']
يوضح المثال السابق الحصول على مصفوفة جديدة تحتوي الحروف كعناصر من النص hello.
4. دالةArray.keys()
تستخدم لاسترداد مفاتيح العناصر في مصفوفة. يتم إرجاع مصفوفة جديدة تحتوي على مفاتيح العناصر فقط في النظام الرقمي.
const arr = ['apple', 'banana', 'orange']; for (const key of arr.keys()) { console.log(key); // 0, 1, 2 }
إضافات لدوال حسابية
ES6 قدم العديد من الإضافات للدوال الحسابية، من بينها:
1- Math.trunc()
: يقوم بإزالة الأرقام العشرية من الرقم المماثل.
Math.trunc(4.9); // 4 Math.trunc(-4.9); // -4
2- Math.sign()
: يقوم بتحديد إشارة الرقم حيث ترجع ب -1 للأرقام السالبة او 1 للأرقام الموجبة او 0 فى حالة الصفر.
Math.sign(-3); // -1 Math.sign(0); // 0 Math.sign(3); // 1
3- Math.cbrt()
: يقوم بإرجاع جذر العدد الثالث
Math.cbrt(27); // 3
4- Math.log10()
: يقوم بإرجاع لوغاريتم العدد في النظام العشري.
Math.log10(1000); // 3
5- Math.log2()
: يقوم بإرجاع لوغاريتم العدد في النظام الثنائي.
Math.log2(8); // 3
6- Math.hypot()
: يقوم بإرجاع الجذر التربيعي لمجموع مربعات الأعداد المعطاة.
Math.hypot(3, 4); // 5
هذه بعض الإضافات الجديدة التي قدمتها ES6 للدوال الحسابية ويوجد المزيد ولكن هذه فقط أمثلة، والتي تساعد على تبسيط العمليات الحسابية في JavaScript.