Дескрипторы свойств javascript поддерживают пользовательские атрибуты?

Я хотел бы определить свойство javascript, используя дескриптор свойства с пользовательскими атрибутами, другими словами, атрибуты, отличные от стандартных "значений", "записываемых" и т.д. ниже, например, я определил свойство с дескриптором свойств, который имеет пользовательский атрибут "customAttr". вызов Object.defineProperty отлично работает, но позже, когда я пытаюсь перебрать атрибуты дескриптора свойства, мой пользовательский атрибут не указан. Это то, что я пытаюсь сделать возможным? Спасибо вам

var o = {};

Object.defineProperty(o, "newDataProperty", {
                                              value: 101,
                                              writable: true,
                                              enumerable: true,
                                              configurable: true,
                                              customAttr: 1
                                            });


var desc2 = Object.getOwnPropertyDescriptor(o, "newDataProperty");

// List the descriptor attributes.
for (var prop in desc2) {
     console.log(prop + ': ' + desc2[prop]);    
}
//PROBLEM: "customAttr" is not listed

Ответ 1

Нет, это невозможно. Это то, что Object.defineProperty делает:

...

  3. Пусть desc является результатом вызова ToPropertyDescriptor с атрибутами в качестве аргумента.

  4. Вызовите внутренний метод O [[DefineOwnProperty]] с аргументами name, desc и true.

  5. Возврат O.

Иными словами, ToPropertyDescriptor просто игнорирует все, что не "перечислимо", "записывается", "настраивается", "значение", "get" или "set":

  • ...

  • Пусть desc - результат создания нового дескриптора свойств, у которого изначально нет полей.

  • Если результатом вызова внутреннего метода [[HasProperty]] объекта Obj с аргументом "enumerable" является true, тогда
    • ...

(повторите шаг 3 для других допустимых свойств дескриптора)

  10. Возвратите desc.

Ответ 2

Воскрешая старый пост здесь, но я нашел эту идею интересной. Вы можете извлечь тот факт, что функции являются объектами в javascript, и использовать функцию get в качестве владельца атрибута:

function setPropertyAttribute(obj, propertyName, attributeName, attributeValue) {
  var descriptor = getCustomPropertyDescriptor(obj, propertyName);

  descriptor.get.$custom[attributeName] = attributeValue;
}

function getPropertyAttributes(obj, propertyName) {
  var descriptor = getCustomPropertyDescriptor(obj, propertyName);

  return descriptor.get.$custom;
}

function getPropertyAttribute(obj, propertyName, attributeName) {
  return getPropertyAttributes(obj, propertyName)[attributeName];
}

function getCustomPropertyDescriptor(obj, prop) {
  var actualDescriptor = Object.getOwnPropertyDescriptor(obj, prop);
  if (actualDescriptor && actualDescriptor.get && actualDescriptor.get.$custom) {
    return actualDescriptor;
  }

  var value = obj[prop];
  var descriptor = {
    get: function() {
      return value;
    },
    set: function(newValue) {
      value = newValue;
    }
  }
  descriptor.get.$custom = {};

  Object.defineProperty(obj, prop, descriptor);
  return Object.getOwnPropertyDescriptor(obj, prop);
}

Тогда:

var obj = {
  text: 'value',
  number: 256
}

setPropertyAttribute(obj, 'text', 'myAttribute', 'myAttributeValue');

var attrValue = getPropertyAttribute(obj, 'text', 'myAttribute'); //'myAttributeValue'

скрипт здесь.