Kyle Simpsons's OLOO adding Multiple properties after Object.create

215 views Asked by At

I just recently learned about Kyle Simpson's coined "OLOO" delegation model (instead of inheritance) and he went about creating objects and delegating properties and functions with a code snippet similar to below:

var Foo = {
    init: function(who) {
        this.me = who;
    },
    identify: function() {
        return "I am " + this.me;
    }
};

var Bar = Object.create(Foo);

Bar.speak = function() {
    alert("Hello, " + this.identify() + ".");
};

var b1 = Object.create(Bar);
b1.init("b1");
var b2 = Object.create(Bar);
b2.init("b2");

b1.speak(); // alerts: "Hello, I am b1."
b2.speak(); // alerts: "Hello, I am b2."

Here, Bar delegates all calls to "init" and "identify" to the "Foo" object but then after Bar is created we have to go through line-by-line and add any other properties to Bar via:

Bar.someAdditionalFunc = function(){ /* Do something else for Bar */ };
Bar.someAdditionalProp = { prop: 'Value' };

My question is this: is there any way to pre-define (or post-define) all these properties for a (potentially) big Bar without using the dot notation (Bar.PropertyName = ...) for each new property?

For example, I was thinking of doing something like this:

var BarTemp = {
    someAdditionalFunc: function(){ /* Do something else for Bar */ },
    someAdditionProp: { prop: 'Value' }
};

var Bar = Object.create(Foo, BarTemp);

And this correctly creates the Bar object with the someAdditionFunc and someAdditionalProp properties created but they are all set to 'undefined'. I suppose this is the correct behavior but I was wondering if I am stuck with using jQuery.extend() or creating another sub-object like so:

var subObject = {
    someAdditionalFunc: function() {},
    someAdditionalProp: { prop: 'value' }
    // ... all other properties we want to add
}

var Bar = Object.create(Foo);
Bar.otherStuff = subObject; 
// Now I always have to reference those properties by:
//    Bar.otherStuff.someAdditionalFunc
// instead of:
//    Bar.someAdditionalFunc

or is there a simpler way to implement/think about this?

1

There are 1 answers

1
Ed_ On BEST ANSWER

There are a couple of options to do this in fewer steps, but it really depends upon your browser support requirements. The second option is also not particularly "simple", either!

Object.setPrototypeOf() (ES6)

Because this is in ES6, it's only really any use if you're using server side code where the JavaScript engine is known, otherwise you'll have to polyfill. See the compatability chart here.

var foo = {
  bar: function() { console.log("bar"); }
}

var baz = {
  someProp: 'a',
  someFunc: function () { console.log("dork"); }
}


Object.setPrototypeOf( baz, foo );
baz.someFunc() // "dork"
baz.bar()      // "bar"

Object.create( proto , propertiesObject ) (ES5)

This is more widely supported, but might still cause you issues with old versions of IE.

Bascially, you were nearly there in your question, except that you need to use property descriptors instead of just a hash of properties and values:

var foo = {
  bar: function() { console.log("bar"); }
}

var b = Object.create( foo, {
  baz: {
    value: function() { console.log("baz") },
    writable: true,      // default: false
    enumerable: true,   // default: false
    configurable: true,  // default: false
  },
  defProps: {
    value: function() { console.log("default"); }
  }
});

b.bar();      // bar
b.baz();      // baz
b.defProps(); // default

for(var prop in b){
 console.log(prop); // baz, bar
}

delete b.defProps;   //typeError
b.defProps = "test"; //typeError

The problem with this, as illustrated with the defProps object above, is that the defaults for the object property descriptors are almost always not what you want, so it ends up being incredibly verbose and even more tedious.