واصفات المواقع

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

هناك نوعان من أدوات الوصف مرتبطة بأي سمة: واصفات البيانات وواصفات البيانات. يتضمن واصف البيانات أزواج المفتاح والقيمة التي تحتوي على قيمة السمة، بغض النظر عما إذا كان ذلك قابلة للكتابة أو قابلة للتهيئة أو قابلة للتعداد. تحتوي واصفات الموصّل على الدوال التي يتم تنفيذها عند تعيين خاصية أو تغييرها أو الوصول إليها.

الموقع نوع الواصف القيمة التلقائية من
Object.defineProperty()
الوصف
[[Value]] البيانات undefined يحتوي على قيمة الموقع.
[[Writable]] البيانات false تحدِّد هذه السياسة ما إذا كان بإمكانك تغيير قيمة الموقع.
[[Get]] إكسسوار undefined دالة getter في السمة، والتي يتم تنفيذها عند إجراء الوصول إلى الموقع.
[[Set]] إكسسوار undefined دالة setter للسمة، والتي يتم تنفيذها عند إجراء البيانات أو تغييرها.
[[Configurable]] كلاهما false إذا كانت هذه السمة false، لا يمكن حذف الموقع. لا يمكن تغيير سماته. إذا كان هذا false [[Writable]] هي true، ويمكن لقيمة الموقع أن ستتغير.
[[Enumerable]] كلاهما false إذا كانت هذه السمة true، يمكنك التكرار على السمة باستخدام التكرارات الحلقية for...in أو القيمة الثابتة Object.keys() .

تستخدم كل واحدة من هذه السمات الاختصار نفسه مثل [[Prototype]]، للإشارة إلى أن هذه الخصائص لا يجب أن يتم الوصول إليها بشكل مباشر. بدلاً من ذلك، استخدم Object.defineProperty() طريقة ثابتة لتحديد أو تعديل خصائص الخاص بك. تقبل Object.defineProperty() ثلاث وسيطات: الكائن الذي يجب اتخاذ إجراء بناءً عليه، مفتاح الخاصية المراد إنشاؤه أو تعديله، وكائن يحتوي على الكلمات الوصفية المرتبطة بالموقع الذي يتم إنشاؤه أو تعديله.

المواقع التي تم إنشاؤها باستخدام Object.defineProperty() تلقائيًا غير قابلة للكتابة أو القابلة للتعداد أو القابلة للتهيئة. مع ذلك، فإنّ أيّ موقع تنشئه إما كجزء من الكائن الحرفي أو باستخدام تدوين النقطة أو القوس وقابلة للكتابة وقابلة للتعداد والقابلة للتهيئة.

const myObj = {};

Object.defineProperty(myObj, 'myProperty', {
  value: true,
  writable: false
});

myObj.myProperty;
> true

myObj.myProperty = false;

myObj.myProperty;
> true

على سبيل المثال، عندما تكون قيمة [[Writable]] هي false، تتم محاولة ضبط قيمة جديدة. التابع للموقع الإلكتروني المرتبط يخفق في صمت خارج الوضع المتشدد، ويعرض خطأ في الوضع المتشدد:

{
    const myObj = {};

    Object.defineProperty(myObj, 'myProperty', {
    value: true,
    writable: false
    });

    myObj.myProperty = false;
    myObj.myProperty;
}
> true

(function () {
    "use strict";
    const myObj = {};

    Object.defineProperty(myObj, 'myProperty', {
    value: true,
    writable: false
    });

    myObj.myProperty = false;
    myObj.myProperty;
}());\
> Uncaught TypeError: "myProperty" is read-only

يعد الاستخدام الفعال للواصفات مفهومًا متقدمًا إلى حد ما، ولكنه فإن فهم الهيكل الداخلي لكائن أمر ضروري لفهم بناء الجملة المتضمنة في العمل على الكائنات بطرق أكثر شيوعًا. على سبيل المثال: تدخل هذه المفاهيم في حيز التنفيذ عند استخدام طريقة Object.create() الثابتة، والتي تمنحك تحكمًا أكثر دقة في أي نماذج أوّلية مرتبطة الخاص بك.

تنشئ ميزة "Object.create()" عنصرًا جديدًا باستخدام كائن حالي. والنموذج الأوّلي. يتيح هذا للعنصر الجديد اكتساب الخصائص والطرق من بيانات أخرى كائن محدد من جانب المستخدم بالطريقة نفسها التي تكتسب بها الكائنات الخصائص من نموذج Object الأولي المضمَّن في JavaScript. عند استدعاء Object.create() باستخدام كائنًا كوسيطة، فإنه ينشئ كائنًا فارغًا بالكائن الذي تم تمريره نموذجه الأوّلي.

const myCustomPrototype = {
  'myInheritedProp': 10
};

const newObject = Object.create( myCustomPrototype );

newObject;
> Object {  }
<prototype>: Object { myInheritedProp: 10 }
  myInheritedProp: 10
  <prototype>: Object { … }

يمكن لـ Object.create استخدام وسيطة ثانية تحدد الخصائص الخاصة تم إنشاء كائن حديثًا باستخدام بنية مشابهة للدالة Object.defineProperty(). أي مفاتيح تعيين الكائنات لمجموعة من سمات الواصف:

const myCustomPrototype = {
  'myInheritedProp': 10
};

const myObj = Object.create( myCustomPrototype, {
        myProperty: {
            value: "The new property value.",
            writable: true,
            configurable: true
        }
  });

myObj;
> Object { … }
    myProperty: "The new property value."
    <prototype>: Object { myInheritedProp: 10 }

في هذا المثال، يستخدم الكائن الجديد (myObj) كائنًا حرفيًا (myCustomPrototype) كنموذج أوّلي، والذي يحتوي بحد ذاته على Object.prototype، مما أدى إلى الحصول على سلسلة من النماذج الأولية الموروثة تسمى سلسلة نموذج أولي. وكل كائن له نموذج أولي، سواء تم تعيينه أو موروثًا، التي تحتوي على نموذج أولي خاص أو موروث. تنتهي هذه السلسلة في النموذج الأوّلي "null" الذي لا يتضمّن نموذجًا أوليًا خاصًا به

const myPrototype = {
  'protoProp': 10
};

const newObject = Object.setPrototypeOf( { 'objProp' : true }, myPrototype );

newObject;
> Object { objProp: true }
    objProp: true
    <prototype>: Object { protoProp: 10 }
        protoProp: 10
        <prototype>: Object { … }

تتوفر الخصائص الموجودة في النموذج الأولي للقيمة في "المستوى الأعلى" لكائن، دون الحاجة إلى الوصول إلى خاصية النموذج الأوّلي مباشرة:

const objectLiteral = {
    "value" : true
};

objectLiteral;
> Object { value: true }
    value: true
    <prototype>: Object { … }

objectLiteral.toString();
"[object Object]"

ينطبق هذا النمط على سلسلة النموذج الأوّلي بأكملها المرتبطة الكائن: عند محاولة الوصول إلى خاصية ما، يبحث المُترجم الفوري عن ذلك. على كل "مستوى" سلسلة النموذج الأوّلي، من أعلى إلى أسفل، حتى تجد العقار أو تنتهي السلسلة:

const myCustomPrototype = {
  'protoProp': "Prototype property value."
};

const myObj = Object.create( myCustomPrototype, {
    myProperty: {
        value: "Top-level property value.",
        writable: true,
        configurable: true
    }
});

myObj.protoProp;
> "Prototype property value."

التحقق من فهمك

أي أدوات الوصف تُعد موصلات؟

[[Get]]
[[Set]]
[[Writable]]