0.1.3 • Published 11 years ago

proteus v0.1.3

Weekly downloads
18
License
-
Repository
github
Last release
11 years ago

Proteus

Declaratively define JavaScript objects and constructor functions (A.K.A. "Classes"), and the instances they produce.

ˈ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

0.1.3

11 years ago

0.1.2

12 years ago

0.1.1

12 years ago

0.1.0

12 years ago

0.0.10

12 years ago

0.0.9

12 years ago

0.0.8

12 years ago

0.0.7

12 years ago

0.0.6

13 years ago

0.0.1

13 years ago