proteus-2
v0.0.3
Published
FORK::: A declarative way of creating objects, properties, and classes in ES5 JavaScript
Downloads
6
Maintainers
Readme
proteus
A declarative way of creating objects, properties, and classes in ES5 JavaScript
ˈprōtēəs; ˈprōˌt(y)oōs
In Greek Mythology a minor sea god (son of Oceanus and Tethys) who had the power of prophecy but who would assume different shapes to avoid answering questions.
From the Greek protos "first."
Overview
Proteus is a little library of utility functions that I put together to help manage creating objects and implementing classical inheritance in JavaScript flavors 1.8+.
Object Creation and Modification
Proteus.create(proto, props)
Interface to Object.create, however, the props argument is a plain object of properties to copy over to the newly created object. Getters and setters will be preserved.
Proteus.defineProperty(obj, name, val, [spec])
Utility method for creating 'plain' properties on an object. Plain being {enumerable: true, writable: true, configurable: true}, the passed spec can override these defaults.
Proteus.defineProperty(obj, "propName", 42);
Proteus.defineProperty(
obj,
"methodName",
function () { /*...*/ },
{enumerable: false}
);
Proteus.defineProperties(obj, list)
Define multiple properties.
Proteus.defineProperties(obj, [
[obj, "propName", 42],
[obj, "methodName", function () {
/*...*/
}, {
enumerable: false
}]
]);
Proteus.defineGetter(obj, name, fn, [spec])
Utility method for creating a getter on an object. The property definition will default to {enumerable: true, configurable: true} unless overridden with the spec object.
Proteus.defineSetter(obj, name, fn, [spec])
Utility method for creating a setter on an object. The property definition will default to {enumerable: true, configurable: true} unless overridden with the spec object.
Proteus.defineGetSet(obj, name, getter, [setter], [spec])
Utility method for creating both a getter and a setter on an object. The property definition will default to {enumerable: true, configurable: true} unless overridden with the spec object.
if setter
is not given, then the getter
function will be used for both getting and setting
Proteus.getPropertyNames(obj)
Get all property names for an object, all the way up the prototype chain.
Proteus.getPropertyDescriptor(obj, name)
Get a property descriptor for an object where ever it may exist in the prototype chain.
Proteus.copyOwnProperties(hidden = false, overwrite = true, supplier, receiver)
Copy properties from supplier
to receiver
. This method will preserve the property definitions from supplier
to receiver
(uses Object.getOwnPropertyDescriptor
under the hood).
Proteus.copyAllProperties(supplier, receiver)
Copy all properties from supplier
to receiver
.
Proteus.applyProperties(supplier, receiver)
Copy all enumerable properties from supplier
to receiver
only if the property does not exist on the receiver
object.
Proteus.applyAllProperties(supplier, receiver)
Copy all properties from supplier
to receiver
, but do not overwrite existing properties on receiver
.
Proteus.merge(receiver, arg1, ..., argN)
Merge enumerable properties from all objects passed as arguments onto receiver
.
Proteus.mergeAll(receiver, arg1, ..., argN)
Merge all properties from all objects passed as arguments onto reciever
.
Proteus.apply(receiver, arg1, ..., argN)
Merge enumerable properties from all objects passed as arguments onto receiver
, only if they do not exist on receiver
.
Proteus.applyAll(receiver, arg1, ..., argN)
Merge all properties from all objects passed as arguments onto receiver
, only if they do not exist on receiver
.
Proteus Utility Methods
Proteus.slice(list, offset = 0, end = list.length)
Return a portion of the array-like object.
Proteus.aliasMethod(name, [scope])
Return a function that is bound to call another function on the current object, or the supplied one.
Proteus.delegateMethod(obj, name, [args, ...])
Delegate a function call to another object. Additional arguments will be prepended to the function call.
Proteus.applyProto(self, [name], args = [])
Apply a method from the self
object's prototype chain.
The name
argument is optional if the function you are invoking from, and the one up the prototype chain you wish to invoke is named. e.g:
var Proteus = require("proteus"),
objA = {
someMethod: function someMethod () {
console.log("I'm object A");
}
},
objB = Proteus.create(objA, {
someMethod: function someMethod () {
Proteus.applyProto(this, arguments);
console.log("I'm object B");
}
})
;
objB.someMethod();
// => I'm object A
// => I'm object B
Proteus.callProto(self, name, [arg1], [...], [argN])
Call a method name
from the self
object's prototype chain passing the remaining arguments as arguments.
Note: the name
parameter is not optional.
Proteus.Class
Proteus.Class
starts off the Proteus inheritance chain (itself is a descendent of Object
). From there you can derive new classes from Proteus.Class
(or any classes that are derived from Proteus.Class
) to develop your class hierarchy.
var MyClass = Proteus.Class.derive({
// props for MyClass
}),
MySubClass = MyClass.derive({
// props for MySubClass
})
;
Deriving Inheritance
ProteusClass.derive(props)
As shown above, use the static methods on the core Proteus.Class
, or the Constructor functions returned by derive
, to derive new subclasses.
In addition, Proteus
allows you to define static properties on your subclass' Constructor function. Simply provide a property self
in the passed properties for your class, and those will be copied to the Constructor function instead of the Constructor's prototype.
var MyClass = Proteus.Class.derive({
self: {
// Static properties for 'MyClass'
myStaticMethod: function () {
return true;
}
},
// All other properties are put on the prototype
instancePropA: "somevalue"
});
MyClass.myStaticMethod(); // => true
(new MyClass()).instancePropA === "somevalue"; // => true
The Inherited Event
When one class is derived from another, and the superclass possesses a function property named inherited
, the function will be called and passed the newly created Constructor function (i.e: the new subclass).
var MyBaseClass = Proteus.Class.derive({
self: {
inherited: function (subclass) {
subclass.superParent = "MyBaseClass";
}
}
}),
MySubClass = MyBaseClass.derive({/* ... */})
;
MySubClass.superParent === "MyBaseClass"; // => true
ProteusClass.__super__ Property
Every class derived from Proteus.Class has a __super__
property that points to its super class' prototype.
var MyBaseClass = Proteus.Class.derive({
someMethod: function () {
// ...
}
}),
MySubClass = MyBaseClass.derive({
someMethod: function () {
MySubClass.__super__.someMethod.call(this);
}
})
;
Including Instance Functionality
ProteusClass.include(obj1, ..., objN)
You can mix-in functionality from other Constructor function prototype's, or plain objects, into Proteus derived classes with the include
method.
If passed a Constructor function, Proteus will copy the function's prototype properties to your Class' prototype. If passed a plain object, it will copy over those properties to the prototype of the class.
// Copy 'OtherClass' prototype properties to 'MyClass' prototype.
MyClass.include(OtherClass);
// Merge the passed object into 'MyClass'
MyClass.include({
// Additional properties for MyClass.prototype
});
The Included Event
When an object, or Constructor function, is included into a Proteus Class its included
function will be called and given the object that it was included into (the Proteus Class Constructor).
var MyModule = Proteus.Class.derive({
self: {
decorators: [],
included: function (includee) {
includee.decorators = this.decorators.slice();
}
}
}),
MyClass = Proteus.Class.derive({/* ... */})
;
MyClass.include(MyModule);
MyClass.decorators; // => []
Extending Your Class
ProteusClass.extend(obj)
You can use a ProteusClass's extend
method to extend another object with its functionality.
var MyClass = Proteus.class.derive({
self: {
someMethod: function () {
// ...
}
}
});
// elsewhere
MyClass.extend(obj);
typeof MyClass.someMethod; // => "function"
The Extended Event
Instantiation
Report an Issue
- Bugs
- Contact the author: [email protected]
License
Copyright (c) 2012 Jerry Hamlet [email protected]
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.