C
carton
Any opinions on this code as part of a general purpose framework?
I expect people will have varying opinions on the use of $ in the
property names. I did it for several reasons: 'interface' is
reserved,
I didn't want to step on 'constructor', and a 'prototype' property on
a
non-function might be confusing.
Gadget is a usage example to make it easier to follow what I'm doing.
var Gadget = createConstructor({
/*
* $inherit specifies another constructor to 'inherit' from.
* The specified constructor must be one that was returned
* by a previous call to createConstructor.
*/
$inherit: Widget,
/*
* This is a list of the methods to be exposed publicly
* on the objects.
*/
$interface: ['method1', 'method2'],
$prototype: {
method1: function() { ... },
method2: function() { ... },
method3: function() { ... },
data1: 'blah'
},
$constructor: function() {
/* Usually call Widget constructor first.
* Don't use Widget.call because that applies an interface
* wrapper that we don't use. See createConstructor below.
* The $constructor property is added as an alternative.
*/
Widget.$constructor.call(this, 'arg1', 'arg2');
/* other normal constructor stuff */
}
});
var createConstructor = function() {
/*
* createInterfaceWrapper takes a list of methods names
* and creates a function that can be applied to an
* object to create a wrapper object that only exposes
* the methods in the list. This is really the point
* of the whole exercise.
*/
function createInterfaceWrapper( methods ) {
return function( obj ) {
var wrapper = {};
for (var i=0; i < methods.length; ++i) {
var method = methods;
wrapper[method] = function(method) {
return function() {
return obj[method](arguments);
};
}(method);
}
return wrapper;
}
}
/*
* Helper function for creating a new object that
* inherits from some prototype object
*/
function inherit(obj, prototype) {
var F = function() {};
F.prototype = prototype;
var newObj = new F();
for (i in obj) {
//Do I need hasOwnProperty here?
newObj = obj;
}
return newObj;
}
return function(params) {
/* I've left out handling of default behavior for properties of
* params that might be missing
*/
params.$interface =
params.$interface.concat(params.$inherit.$interface);
var interfaceWrapper = createInterfaceWrapper(params.
$interface);
var ctor = function() {
params.$constructor.apply(this, arguments);
return interfaceWrapper(this);
};
ctor.prototype = inherit(params.$prototype,
params.$inherit.prototype);
/*
* Save $interface and $constructor for use by other
* constructors that want to 'inherit' from this one
*/
ctor.$interface = params.$interface;
ctor.$constructor = params.$constructor;
return ctor;
}
}();
I expect people will have varying opinions on the use of $ in the
property names. I did it for several reasons: 'interface' is
reserved,
I didn't want to step on 'constructor', and a 'prototype' property on
a
non-function might be confusing.
Gadget is a usage example to make it easier to follow what I'm doing.
var Gadget = createConstructor({
/*
* $inherit specifies another constructor to 'inherit' from.
* The specified constructor must be one that was returned
* by a previous call to createConstructor.
*/
$inherit: Widget,
/*
* This is a list of the methods to be exposed publicly
* on the objects.
*/
$interface: ['method1', 'method2'],
$prototype: {
method1: function() { ... },
method2: function() { ... },
method3: function() { ... },
data1: 'blah'
},
$constructor: function() {
/* Usually call Widget constructor first.
* Don't use Widget.call because that applies an interface
* wrapper that we don't use. See createConstructor below.
* The $constructor property is added as an alternative.
*/
Widget.$constructor.call(this, 'arg1', 'arg2');
/* other normal constructor stuff */
}
});
var createConstructor = function() {
/*
* createInterfaceWrapper takes a list of methods names
* and creates a function that can be applied to an
* object to create a wrapper object that only exposes
* the methods in the list. This is really the point
* of the whole exercise.
*/
function createInterfaceWrapper( methods ) {
return function( obj ) {
var wrapper = {};
for (var i=0; i < methods.length; ++i) {
var method = methods;
wrapper[method] = function(method) {
return function() {
return obj[method](arguments);
};
}(method);
}
return wrapper;
}
}
/*
* Helper function for creating a new object that
* inherits from some prototype object
*/
function inherit(obj, prototype) {
var F = function() {};
F.prototype = prototype;
var newObj = new F();
for (i in obj) {
//Do I need hasOwnProperty here?
newObj = obj;
}
return newObj;
}
return function(params) {
/* I've left out handling of default behavior for properties of
* params that might be missing
*/
params.$interface =
params.$interface.concat(params.$inherit.$interface);
var interfaceWrapper = createInterfaceWrapper(params.
$interface);
var ctor = function() {
params.$constructor.apply(this, arguments);
return interfaceWrapper(this);
};
ctor.prototype = inherit(params.$prototype,
params.$inherit.prototype);
/*
* Save $interface and $constructor for use by other
* constructors that want to 'inherit' from this one
*/
ctor.$interface = params.$interface;
ctor.$constructor = params.$constructor;
return ctor;
}
}();