2

I'm working on creating an object definition to encapsulate several properties. I have 4 requirements for this object:

  • more than one instance can be created at any time
  • only properties defined on the object can be set/get
  • the object must be stringify-able (just the properties and associated values)
  • the stringified version must be parse-able and return the object

This is a simplified version of what I have so far:

function Car() {
    
    var _make;

    Object.defineProperty(this, 'make', {
        get: function() {
            return _make;
        },
        set: function(make) {
            _make = make;           
        }
    });
    Object.preventExtensions(this);
}

I'm unsure if this is the simplest approach for defining an object with getters and setters. Is there an alternative to using Object.defineProperty, or is this the new norm?

This approach also requires me to write my own stringify method (see below) since calling JSON.stringify will strip off functions, and this will strip off make. Is there an alternative to writing my own? Can I change my object definition somehow?

Car.prototype.stringify = function () {
    return JSON.stringify({ make: this.make});
}

Additionally, I must supply an optional constructor arg to be able to instantiate a Car from a JSON object:

function Car(car) {
    var _make;
    if(car !== undefined && car != null) {
        _make = car.make;
    }
    ...
}

Again, is this the best approach to meet all the requirements?

user1491636
  • 2,355
  • 11
  • 44
  • 71
  • 2
    "`JSON.stringify` will strip off functions..." -- `make` is not a function. It is an *accessor property* that *has* functions. That said, it's not clear to me why you don't just use a normal data property for `make` and use `this.make` anywhere you currently use `_make`. (If you have functions inside your constructor that use a different `this`, you can capture the desired `this` with `var that = this` (or similar) and use `that.make`.) – apsillers Dec 08 '14 at 16:43
  • You might want to look at [Records](https://github.com/facebook/immutable-js/blob/3.3.0/type-definitions/Immutable.d.ts#L1578-L1637) of [Immutable](http://facebook.github.io/immutable-js/). – Felix Kling Dec 08 '14 at 16:46
  • @apsillers Not quite sure exactly what you're proposing. Do you mind changing the following fiddle with your proposal: http://jsfiddle.net/xx1qp1e8/1/ – user1491636 Dec 08 '14 at 18:05
  • 1
    @user1491636 Sure: http://jsfiddle.net/xx1qp1e8/2/ I've made `this.make` a simple data property and eliminated `_make` entirely. Also, I've simplified your `stringify` method. (Note that with `defineProperty`, you must explicitly use `enumerable: true` to make the property enumerable and included in `JSON.stringify` output.) If you have a reason why my proposal won't work for your actual needs, clarify it in your question. – apsillers Dec 08 '14 at 18:10
  • @apsillers Ah ok, makes more sense... much simpler. Also, the Car stringify method is really not needed anymore I guess. Thanks! – user1491636 Dec 08 '14 at 18:12
  • @apsillers Follow-up question... Is there an alternative to defining object variables with `this.var=undefined`? If I had a list of 20 vars, setting each to undefined seems a little odd. Is this the only way I can fulfill my requirements? – user1491636 Dec 08 '14 at 18:29
  • @user1491636 You can loop over a list of property names as strings and use bracket notation: `this[propName] = undefined;` So a full example might be `var pList = ['a','b']; for(var i=0;i – apsillers Dec 08 '14 at 18:31

1 Answers1

4

To show up make property while using JSON.stringify, you have to set the enumerable to True (By default, False).

configurable: true if and only if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object. Defaults to false.

enumerable: true if and only if this property shows up during enumeration of the properties on the corresponding object. Defaults to false. function Car() {

var _make;

Object.defineProperty(this, 'make', {
    get: function() {
        return _make;
    },
    set: function(make) {
        _make = make;           
    },
    enumerable:true 
});
Object.preventExtensions(this);

}

Akshay Pratap Singh
  • 3,197
  • 1
  • 24
  • 33