Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Data Descriptors in literal notation (object creation)

I know that from ECMAScript5 there are two ways of creating objects.

1/ Literal notation which (by default) sets all internal data properties to true (writable, configurable and enumerable.

2/ Using Object.create method which (by default) sets all data descriptors to false.

Is it valid to set enumerable to false in literal notation? While doing this on object2 shouldn't Object.keys(obj2) return an empty array?

var obj1 = Object.create(null, {
  'name': {value: 'first object name'},
  'surename': {value: 'first object surname', enumerable: true, configurable: true}
});

var obj2 = {'x': {value: 10, enumerable: false}};

console.log(Object.keys(obj1)); // ["surename"] 
console.log(Object.keys(obj2)); // ["x"]

JsFiddle link

like image 928
Chris Hermut Avatar asked Mar 19 '23 07:03

Chris Hermut


1 Answers

I too searched up and down for this, and couldn't find anything. You can however define getter and setter functions if that's all you need, like this:

var x = {
  y: 6,
  get foo() {
    return this.y + 10;
  },
  set bar(value) {
    this.y = foo - 1;
  }
};

x.y; // 6
x.foo; // 16
x.bar = 8;
x.y; // 7
x.foo; // 17

I also defined a small utility to ease defining properties in literal notation. Here it is:

/*
 * Facilitates defining properties with advanced attributes in literal notation.
 *
 * Example:
 *   var foo = {
 *     x: 6,
 *     bar: new Property({
 *       enumerable: false,
 *       get: function () {
 *         return this.x + 1
 *       }
 *     })
 *   }
 *   foo.bar // value is an object of type Property
 *   Properties.eval(foo)
 *   foo.bar // value is now 7
 */

'use strict'

/**
 * Constructor.
 *
 * @param {object} descriptor
 * the property descriptor, in the format used by <code>Object.defineProperty</code>
 *
 * @returns {Property}
 *
 * @see Object.defineProperty
 */
var Property = function (descriptor) {
  this.descriptor = descriptor
  Object.freeze(this)
}

Property.prototype.toString = function () {
  return 'Property'
}

var Properties = new Object(null)

/**
 * Replace all properties of type <code>Property</code> contained in the
 * specified object with the value associated with the <code>Property</code>.
 *
 * @param {object} object
 * the object
 */
Properties.eval = function (object) {
  // recursive
  for (var propertyName in object) {
    if (object.hasOwnProperty(propertyName)) {
      var property = object[propertyName]
      if (property instanceof Property) {
        Object.defineProperty(object, propertyName, property.descriptor)
        property = object[propertyName]
      }
      if (property instanceof Object) {
        Properties.eval(property)
      }
    }
  }
}
like image 91
Alvin Thompson Avatar answered Apr 02 '23 14:04

Alvin Thompson