اذهب إلى المحتوى

مفاتيح الكائنات وقيمها ومدخلاتها في جافاسكربت


صفا الفليج

لنأخذ راحة صغيرة بعيدًا عن بنى البيانات ولنتحدّث عن طريقة المرور على عناصرها.

رأينا في الفصل السابق التوابِع map.keys()‎ وmap.values()‎ وmap.entries()‎. هذه التوابِع عامّة وقد اتّفق معشر المطوّرين على استعمالها عند التعامل مع بنى البيانات. ولو أنشأنا بنية بيانات من الصفر بيدنا، فعلينا توفير "تنفيذ" تلك التوابِع أيضًا. هي أساسًا مدعومة لكلّ من:

  • الخرائط Map
  • الأطقم Set
  • المصفوفات Array

كما وتدعم الكائنات العادية توابِع كتلك التوابِع باختلاف بسيط في صياغتها.

التوابِع keys وvalues وentries

هذه هي التوابِع المتاحة للتعامل مع الكائنات العادية:

لاحظ رجاءً الفروق بينها وبين الخارطة مثلًا:

  الخارطة الكائن
صياغة الاستدعاء map.keys() Object.keys(obj)‎ لكن ليس obj.keys()‎
قيمة الإعادة مُكرَّر مصفوفة ”حقيقية“

أوّل فرق واضح جليّ: علينا استدعاء Object.keys(obj)‎ لا obj.keys()‎. ولكن لماذا؟ السبب الأساس هو مرونة الاستعمال. لا تنسَ بأنّ الكائنات هي أساس كلّ بنية بيانات معقّدة في جافاسكربت. يحدث بأنّ لدينا كائن طوّرناه ليحمل بيانات data محدّدة، وفيه التابِع data.values()‎، ولكنّا نريد أيضًا استدعاء Object.values(data)‎ عليه.

الفرق الثاني هو أنّ التوابِع Object.* تُعيد كائنات مصفوفات ”فعلية“ لا مُتعدَّدات فقط. يعزو ذلك لأسباب تاريخية بحتة. خُذ هذا المثال:

let user = {
  name: "John",
  age: 30
};
  • Object.keys(user) = ["name", "age"]‎
  • Object.values(user) = ["John", 30]‎
  • Object.entries(user) = [ ["name","John"], ["age",30] ]‎

وهذا مثال آخر عن كيف نستعمل Object.values للمرور على قيم الخاصيات:

let user = {
  name: "John",
  age: 30
};

// نمرّ على القيم
for (let value of Object.values(user)) {
  alert(value); // ‫John ثمّ 30
}

تتجاهل هذه التوابِع الخاصيات الرمزية كما تتجاهل حلقة for..in الخاصيات التي تستعمل Symbol(...)‎ مفاتيح لها، فهذه التوابِع أعلاه تتجاهلها أيضًا

غالبًا يكون هذا ما نريد، ولكن لو أردت المفاتيح الرمزية أيضًا، فعليك استعمال التابِع المنفصل Object.getOwnPropertySymbols إذ يُعيد مصفوفة بالمفاتيح الرمزية فقط. هناك أيضًا التابِع Reflect.ownKeys(obj) إذ يُعيد المفاتيح كلها.

تعديل محتوى الكائنات

ليس للكائنات تلك التوابِع المفيدة المُتاحة للعناصر (مثل map وfilter وغيرها). لو أردنا تطبيق هذه التوابِع على الكائنات فيجب أوّلًا استعمال Object.entries وبعدها Object.fromEntries:

  1. استعمل Object.entries(obj)‎ لتأخذ مصفوفة لها أزواج ”مفتاح/قيمة“ من الكائن obj.
  2. استعمل توابِع المصفوفات على تلك المصفوفة (مثلًا map).
  3. استعمل Object.fromEntries(array)‎ على المصفوفة الناتج لتُحوّلها ثانيةً إلى كائن.

إليك مثالًا لدينا كائنًا فيه تسعير البضائع، ونريد مضاعفتها (إذ ارتفع الدولار):

let prices = {
  banana: 1,
  orange: 2,
  meat: 4,
};

let doublePrices = Object.fromEntries(
  // ‫نحوّله إلى مصفوفة، ثمّ نستعمل الطقم، ثمّ يُعيد إلينا fromEntries الكائن المطلوب
  Object.entries(prices).map(([key, value]) => [key, value * 2])
);

alert(doublePrices.meat); // 8

ربّما تراه صعبًا أوّل وهلة، ولكن لا تقلق فسيصير أسهل أكثر متى ما بدأت استعمالها مرّة واثنتان وثلاث. يمكن أن نصنع سلسلة فعّالة من التعديلات بهذه الطريقة:

تمارين

مجموع الخاصيات

الأهمية: 5

أمامك كائن salaries وفيه بعض الرواتب. اكتب دالة sumSalaries(salaries) تُعيد مجموع كلّ الرواتب، باستعمال Object.values وحلقة for..of. لو كان الكائن فارغًا فيجب أن يكون الناتج صفرًا 0.

مثال:

let salaries = {
  "John": 100,
  "Pete": 300,
  "Mary": 250
};

alert( sumSalaries(salaries) ); // 650

الحل

function sumSalaries(salaries) {

  let sum = 0;
  for (let salary of Object.values(salaries)) {
    sum += salary;
  }

  return sum; // 650
}

let salaries = {
  "John": 100,
  "Pete": 300,
  "Mary": 250
};

alert( sumSalaries(salaries) ); // 650

أو يمكننا (لو أردنا) معرفة المجموع باستعمال Object.values والتابِع reduce:

// ‫يمرّ reduce على مصفوفة من الرواتب،
// ويجمعها مع بعضها ويُعيد الناتج
function sumSalaries(salaries) {
  return Object.values(salaries).reduce((a, b) => a + b, 0) // 650
}

عدد الخاصيات

الأهمية: 5

اكتب دالة باسم count(obj)‎ تُعيد عدد الخاصيات داخل الكائن:

let user = {
  name: 'John',
  age: 30
};

alert( count(user) ); // 2

حاوِل أن تكون الشيفرة بأصغر ما أمكن.

ملاحظة: أهمِل الخاصيات الرمزية وعُدّ فقط تلك ”العادية“.

الحل

function count(obj) { 
  return Object.keys(obj).length;
}

ترجمة -وبتصرف- للفصل Object.keys, values, entries من كتاب The JavaScript language

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...