Properties in JavaScript

JavaScript doesn’t inherently support properties in the same way that .net languages do, which is a shame since the syntax really helps simplify access internalized data in a structured way.

There’s a common solution to this in JavaScript, that exploits the fact that JavaScript function arguments are optional. A property function will have a single argument. If the argument is undefined then the current call is a ‘get’, otherwise it’s a ‘set’. jQuery has many good examples of this, for example the val() method:

var value = $('input').val(); // Getter
$('input').val(123); // Setter

It isn’t particularly hard to define a method this way, below is an example class with a single property, ‘name’:

// A new class
var MyClass = function() {
    var _name;

    this.name = function(value) {
        if (value !== undefined)
            _name = value;

        return _name;
    };
};

// Example usage
var instance = new MyClass();
instance.name('Phil');
var name = instance.name(); // name = 'Phil'

This way of doing things is achieves the desired effect, but ends up being overly verbose if you have a lot of properties that are just wrappers around a value, like an auto-implemented property is in C#.

I came up with the solution below while I was working on findthatrobot.com. It helps in the creation of auto-implemented like properties, as well as allowing the getter and setter to be customized, or just one of the two, creating a read-only or write-only property.

With this function a property can be created as such:

var MyClass = function() {
    var customPropertyValue;

    // Auto-implemented proeprty
    this.prop1 = createProperty();

    // Custom getter and setter
    this.prop2 = createProperty({
        get: function() { return customPropertyValue; },
        set: function(value) { customPropertyValue = value; }
    });
};

And here is the ‘createProperty’ function:

var createProperty = function(getSet) {
    var _value;
    var autoImplement = {
        get: function() { return _value; },
        set: function(value) { _value = value; return _value; }
    };

    getSet = getSet || autoImplement;

    var get = getSet.get || function() { throw new Error('No get method defined for this property.'); },
        set = getSet.set || function() { throw new Error('No set method defined for this property.'); };

    return function(value) {
        if (value !== undefined)
            return set(value);

        return get();
    };
};
view raw gistfile1.js This Gist brought to you by GitHub.

Phil

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>