user656925
user656925

Reputation:

Is it possible to create a new type that is more dynamic?

Probably not the correct word. But I want to create a new type in JavaScript. It would have the simple property that one could do this:

var inst = new SomeType();
inst.key1.key2 = 'something';
inst.key1.key1.key3 = 'something';

Basically you wouldn't have to declare an object literal to extend further. It would create one automatically.

This would allow me to build complex structures without having to worry about checking for the existence of a property to extend off of.

Instead of doing

inst.key1 = {};

inst.key1.key2 = 'data';

one could just do

inst.key1.key2 = 'data';

and the

inst.key1 = {};

would be automatic, i.e. would happen internally.

This does have a practical purpose. Particularly I have a registry pattern which I would use this new type to organize data using a more hierarchical approach.

Also, I see a pattern, common in libraries, that tests for the existence of an object literal and then creates one if it does not exist.

This is a common idiom it seems.

Upvotes: 6

Views: 259

Answers (2)

user656925
user656925

Reputation:

Because javascript does not support operator overloading, one could create a really ugly fake operator called ._ as such. If someone wants to implement ._ please edit answer.

http://jsfiddle.net/586Sc/

var Obj = function () {
    this.hold = {};
};

Obj.prototype._ = function (key) {
    //implement here;
    return this;
};

var obj = new Obj();

obj._('key1')._('key2')._('key3') = 'barbarella';
console.log(test);

Upvotes: 0

Rob W
Rob W

Reputation: 348992

What you'd like to get can easily be achieved with Harmony proxies (MDN). However, this API is not yet stable, so it's fine to use it in non-critical hobby code, but don't use it in production code (yet).

Here's an extremely simple example:

function getFreeChain(object) {
    var handler = {
        get: function(target, name) {
            if (name in target)
                return target[name];
            var newTarget = target[name] = {};
            return new Proxy(newTarget, handler);
        }
    };
    return new Proxy(object, handler);
}

// Usage:
var obj = {};
var magicalObj = getFreeChain(obj);
magicalObj.a.b.c.d.e.g = 1;
console.log(magicalObj.a.b.c.d.e.g); // 1
console.log(obj.a.b.c.d.e.g);        // 1
obj.x.y.z = 1;                       // TypeError: obj.x is undefined

Note: My example is an implementation of the latest Proxy specification, which is only supported by Firefox . Chrome only supports an old, significantly different version of the API, which can be enabled by turning on "Experimental JavaScript" at chrome://flags/. This old API is ugly, and implementing the previous would require significantly more lines of code, so I'll leave this as an exercise to the reader.

Oh, there's a library called DirectProxies.js (superseded by harmony-reflect) which brings the simple Proxy API to Chrome. After including the this library, the previous code will work in Firefox and Chrome (with experiments enabled): http://jsfiddle.net/PAhYL/

Upvotes: 7

Related Questions