مهيئ الكائنات في JavaScript

من موسوعة حسوب

يمكن تهيئة الكائنات باستخدام new Object()‎ أو الدالة Object.create()‎ أو باستخدام الشكل المختصرة (initializer notation). إنَّ مُهيّئ الكائنات هو قائمة فيها «صفر» زوج أو أكثر من أسماء الخاصيات مع القيم المرتبطة بها، مفصولةٌ بفواصل، ويحيط بها قوسين معقوفين {}.

البنية العامة

var o = {};
var o = {a: 'foo', b: 42, c: {}};

var a = 'foo', b = 42, c = {};
var o = {a: a, b: b, c: c};

var o = {
  property: function ([parameters]) {},
  get property() {},
  set property(value) {}
};

البنى الجديدة في ECMAScript 2015

رجاءً ارجع إلى جدول التوافقية لترى ما هو دعم هذه البنى، إذ إنَّ هذه البنى ستعطي أخطاءً في المتصفحات غير الداعمة لها.

// أسماء الخاصيات المختصرة
var a = 'foo', b = 42, c = {};
var o = {a, b, c};

// أسماء الدوال المختصرة
var o = {
  property([parameters]) {}
};

// أسماء الخاصيات المحسوبة
var prop = 'foo';
var o = {
  [prop]: 'hey',
  ['b' + 'ar']: 'there'
};

الوصف

مُهيّئ الكائنات هو تعبيرٌ (expression) يصف عملية تهيئة الكائنات من النوع Object؛ والكائنات تتألف من خاصيات (properties) التي تُستخدَم لوصف الكائن، وقيم تلك الخاصيات يمكن أن تكون إما قيمًا أوليّةً (primitive) أو كائنات أخرى.

إنشاء الكائنات

يمكن إنشاء كائن فارغ دون خاصيات مرتبطة به كما يلي:

var object = {};

لكن ميزة استخدام الشكل المختصر هو تمكين إنشاء كائنات لها خاصيات مُعرَّفة داخل القوسين المعقوفين، إذ يمكن ذكر الخاصيات وقيمها على الشكل key: value ويُفصَل بين تلك الأزواج بفاصلة ,. الشيفرة الآتية تُنشِئ كائنًا له ثلاث خاصيات أسماؤها هي foo و age و baz، وقيم تلك الخاصيات هي السلسلة النصية "bar" والعدد 42 وكائن آخر (على التوالي وبالترتيب).

var object = {
  foo: 'bar',
  age: 42,
  baz: {myProp: 12}
}

الوصول إلى الخاصيات

بعد إنشاء الكائن، فربما ترغب بقراءة الخاصيات أو تغييرها، ويمكن الوصول إلى خاصيات الكائن عبر طريقة النقطة (dot notation) أو طريقة الأقواس (bracket notation)، راجع صفحة الوصول إلى الخاصيات لمزيدٍ من المعلومات.

object.foo; // "bar"
object['age']; // 42

object.foo = 'baz';

تعريف خاصيات جديدة

صحيحٌ أننا نستطيع إضافة الخاصيات إلى الكائن عند تعريفه، لكن ستحتاج في غالب الأحيان إلى إضافة خاصيات جديدة تابعة لأحد الكائنات:

var a = 'foo', 
    b = 42,
    c = {};

var o = { 
  a: a,
  b: b,
  c: c
};

أما في ECMAScript 2015، فهنالك شكلٌ مختصرٌ لفعل نفس ما سبق:

var a = 'foo', 
    b = 42, 
    c = {};

// أسماء الخاصيات المختصرة
var o = {a, b, c};

// بصيغة مختلفة
console.log((o.a === {a}.a)); // true

أسماء الخاصيات المكررة

عند استخدام نفس الاسم لأكثر من خاصية، فستُعتمَد قيمة آخر خاصية:

var a = {x: 1, x: 2};
console.log(a); // {x: 2}

تعريف الدوال

يمكن أن تكون إحدى خاصيات الكائن دالةً أو getter أو setter:

var o = {
  property: function ([parameters]) {},
  get property() {},
  set property(value) {}
};

هنالك شكلٌ مختصرٌ جديدٌ في ECMAScript 2015، الذي أصبحت فيه الكلمة المحجوزة function غير ضرورية:

// أسماء الدوال المختصرة
var o = {
  property([parameters]) {},
  *generator() {}
};

أسماء الخاصيات المحسوبة

بدءًا من ECMAScript 2015 أصبح شكل تعريف الكائنات يدعم استخدام أسماء محسوبة للخاصيات، وهذا يعني أنَّنا نستطيع وضع تعبير (expression) ضمن قوسين مربعين [] وستُحسَب قيمة التعبير وتُستخدَم اسمًا للخاصية. ويمكنك استخدام نفس الشكل لقراءة وضبط خاصيات كائن موجود مسبقًا:

// أسماء الخاصيات المحسوبة
var i = 0;
var a = {
  ['foo' + ++i]: i,
  ['foo' + ++i]: i,
  ['foo' + ++i]: i
};

console.log(a.foo1); // 1
console.log(a.foo2); // 2
console.log(a.foo3); // 3

var param = 'size';
var config = {
  [param]: 12,
  ['mobile' + param.charAt(0).toUpperCase() + param.slice(1)]: 4
};

console.log(config); // {size: 12, mobileSize: 4}

تعديل كائن prototype

إذا عرّفنا خاصيةً بالشكل ‎__proto__: value أو الشكل ‎"__proto__": value فلن تُنشَأ خاصيةٌ باسم __proto__ وإنما سيتغير الكائن prototype إذا كانت القيمة المُسنَدَة إليه هي كائن أو null.

var obj1 = {};
assert(Object.getPrototypeOf(obj1) === Object.prototype);

var obj2 = {__proto__: null};
assert(Object.getPrototypeOf(obj2) === null);

var protoObj = {};
var obj3 = {'__proto__': protoObj};
assert(Object.getPrototypeOf(obj3) === protoObj);

var obj4 = {__proto__: 'not an object or null'};
assert(Object.getPrototypeOf(obj4) === Object.prototype);
assert(!obj4.hasOwnProperty('__proto__'));

لا يُسمَح إلا بتغيير كائن prototype إلا مرةً واحدةً عند تعريف الكائن، وإلا فسيرمى خطأ SyntaxError.

الفرق بين تعريف الكائنات وصيغة JSON

الصيغة المختصرة لتعريف الكائنات لا تُماثل صيغة JSON (اختصارٌ للعبارة JavaScript Object Notation)؛ فعلى الرغم من أنّهما تبدوان شبيهتين ببعضهما بعضًا، لكن هنالك بعض الاختلافات بينهما:

  • لا تسمح صيغة JSON إلا بتعريف الخاصيات باستخدام الشكل ‎"property": value، ويجب أن يحاط اسم الخاصية بعلامتَي اقتباس مزدوجتين، ولا يمكن استخدام الأشكال المختصرة لتعريف الخاصيات.
  • يُسمَح باستخدام السلاسل النصية والأرقام والمصفوفات والقيمة true و false و null وكائنات JSON الأخرى فقط في صيغة JSON.
  • لا يمكن إسناد دالة إلى إحدى الخاصيات في صيغة JSON.
  • الكائنات مثل الكائن Date ستصبح سلاسل نصية بعد استدعاء الدالة JSON.parse()‎.
  • الدالة JSON.parse()‎ سترفض أسماء الخاصيات المحسوبة وسترمي خطأً. 

دعم المتصفحات

الميزة Chrome Firefox Internet Explorer Opera Safari
الدعم الأساسي نعم نعم نعم نعم نعم
أسماء الخاصيات المحسوبة 47 34 غير مدعومة 34 8
أسماء الخاصيات والدوال المختصرة 47 34 غير مدعومة 34 9

على النقيض من متصفح IE، يدعم متصفح Edge كل هذه الميزات.

مصادر ومواصفات