-
Notifications
You must be signed in to change notification settings - Fork 3
GSet API
Lets you create GSet objects.
var gset1 = new GSet(source, scheme);
var gset2 = new GSet(source, scheme, signature);
var gset3 = new GSet(source, scheme, gate);
var gset4 = new GSet(source, scheme, signature, gate);
var gset5 = new GSet(source, scheme, gate, signature);
-
source The scope object for GSet methods.
-
scheme An object-literal or existing GSet, listing the instance methods.
-
signature (Optional) A unique object reference to retrieve the source object from this instance.
-
gate (Optional) A function to monitor and/or deny access to instance methods.
A GSet instance is a collection of methods that are scoped to a given object (it's source parameter). A GSet instance offers "live" access and manipulation of an object and it's members, without risking unwanted exposure.
The scheme parameter is similar to the object-literal used when prototyping, except GSet interprets, indexes and compiles each key as a method of the source parameter. Once instantiated, a GSet instance may not be changed - however, it's compiled scheme and internal attributes may be cloned for new instances.
The gate and signature are optional and order-independent parameters. The gate is a function that executes before all methods, and can prevent invoking a method by returning false
. The signature is an object which can retrieve a GSet's source object later. (This is useful for routines that receive GSet instances).
While scheme functions behave like any prototyped method, GSet interprets non-functions as mapped methods. Mapped methods are compiled into internal configuration objects, which abstracts getter and setter functions as discrete behaviors for get, vet, and set (or GVS) actions. The built-in _gset method invokes a map, when passed it's alias (or key within the scheme). As a convenience, GSet appends to itself, curried methods that invoke _gset, for each map, using the alias for the method name.
The syntax for defining mapped methods is based on the object-type and structure of the non-function value. To further reduce the code needed to describe common methods, GSet interprets both explicit and implied maps.
Note: GSet will ignore maps that do not support either action.
Explicit maps use a structured array, whose indices represent one aspect of the GVS abstraction; that is, a get-index, vet-index, and set-index. Each index accepts certain object-types, and otherwise resolves the index, based on the boolean equivalent of unrecognized object types.
Note: Contrary to convention, an empty array is not interpreted as a map with no get or set behaviors. Rather, this structure is seen as an implied map with full-access to the member matching the map's alias.
The first index of an explicit map is the get-index, which may be referred to as the get-function (when populated by a function) or get-property (when populated by a string). This behavior is invoked when the _gset method does not passed values to set.
As a string, the get-index identifies which member of the source object to return. If the member does not exist, the _gset method returns undefined
.
var myGSet = new GSet(obj,
{
name: ['userName']
}
);
As a function, the get-index is invoked with the source object as it's scope. Get-functions must return a value. If not, GSet will ignore the map during instantiation. (The function is checked using a rudimentary string comparison.)
var myGSet = new GSet(obj,
{
name: [
function () {
return this.userName;
}
]
}
);
As an unrecognized truthy value, the get-index is treated as a string, whose value is the map's alias.
var myGSet = new GSet(obj,
{
name: [1]
}
);
As an unrecognized falsy value, the _gset method will decline get-actions for this map.
var myGSet = new GSet(obj,
{
name: [0,1]
}
);
Note: The example above can not use [0]
, since this compiles into a map with no support for either getting or setting.
The second index of an explicit map is the vet-index, which may be referred to as the vet-function (when populated by a function), or vet-property (when populated by a string or array of strings). This behavior is invoked when the _gset method is passed values to set, before the set behavior is observed.
If the set-index is omitted, a truthy vet-index will permit set-actions for the map. With an omitted set-index, the same get-property or get-function will be used for getting and setting. When the map does not support get-actions, the map's alias will serve as the member to target when setting.
Note: Functions that are invoked for both get and set behaviors, may analyze the object returned by GSet.getContext to fork their logic.
As a string or array of strings, the vet-index requires each passed value (to set) match one string. If one value does not match a string from a vet-property, _gset denies the set-action and returns false
.
var myGSet = new GSet(obj,
{
name: [
0,
['string','number']
]
}
);
As a function, the vet-index is invoked with the source object as it's scope. Vet-functions must return a value, and that value should be "truthy" in order to permit the set-action. If the vet-function does not have a return statement, GSet will ignore the map during instantiation. (The function is checked using a rudimentary string comparison.)
var myGSet = new GSet(obj,
{
name: [
0,
function (x, y) {
return typeof x === typeof y;
}
]
}
);
As an unrecognized truthy value, the vet-index is skipped, and any value may be set.
var myGSet = new GSet(obj,
{
name: [
0,
1
]
}
);
As an unrecognized falsy value, the vet-index is skipped, and support for setting is determined by the set-index alone.
var myGSet = new GSet(obj,
{
name: [
1,
0
]
}
);
Note: The example above can not use [0,0]
, since this compiles into a map with no support for either getting or setting.
The third index is the set-index, which may be referred to as the set-function (when populated by a function), or set-property (when populated by a string). This behavior is invoked when the _gset method is passed values to set, after the vet behavior validates them.
As a string, the set-index identifies which member of the source object to assign the first passed value. If the member does not exist, the _gset method will add the member to the source object.
var myGSet = new GSet(obj,
{
name: [
0,
0,
'userId'
]
}
);
As a function, the set-index is invoked with the source object as it's scope. The set-function may return a value, to signal it's success or failure with setting the passed value(s) - the _gset method converts this to a boolean. If the set-function does not return a value (or returns undefined
), _gset will assume the set-action succeeded and return true
.
var myGSet = new GSet(obj,
{
name: [
0,
0,
function (first, last, salutation) {
this.fullName = (salutation ? salutation + ' ' : '') + first + ' ' + last;
}
]
}
);
As an unrecognized truthy value, the set-index is treated as a string, whose value is the map's alias.
var myGSet = new GSet(obj,
{
name: [
0,
0,
1
]
}
);
As an unrecognized falsy value, the _gset method will decline set-actions for this map; this value overrules a truthy vet-index.
var myGSet = new GSet(obj,
{
name: [
1,
1,
0
]
}
);
Note: The example above can not use [0,1,0]
, since this compiles into a map with no support for either getting or setting.
Implied maps use a further shortened syntax, to define maps that support common getter and setter actions. Below are the special objects and structures interpreted by GSet, along with an explicit counterpart.
An empty array is interpreted as a map with get & set support, for a member in the source object that matches the alias.
var myGSet = new GSet(obj,
{
name: []
}
);
This explicit map, compiles into an instance with the same methods.
var myGSet = new GSet(obj,
{
name: [
1,
1,
1
]
}
);
The final GSet instance - compiled with either form - would then invoke this map as follows.
// via same-name methods
myGSet.name(); // getting
myGSet.name('any value'); // setting
// via the _gset method
myGSet._gset('name'); // getting
myGSet._gset('name', 'any value'); // setting
A non-array value is interpreted as a map that "gets" (i.e., returns) the given value. To return an array, pair a nested array within the scheme parameter; the _gset method will return a copy of the nested array.
Unlike methods which reference the source object's member, these maps net methods that return static/unchanging values, which are not necessarily related to the source object.
Note: Object references are passed as is, which may allow unwanted access and manipulation.
var myGSet = new GSet(obj,
{
id: 123,
type: 'some string',
thing: someObjectReference,
groups: [['dev', 'admin', 'shared']]
}
);
This explicit map, compiles into an instance with the same methods.
var myGSet = new GSet(obj,
{
id: [
function () {
return 123;
}
],
type: [
function () {
return 'some string';
}
],
thing: [
function () {
return someObjectReference;
}
],
groups: [
function () {
return ['dev','admin','shared'];
}
]
}
);
The final GSet instance - compiled with either form - would then invoke this map as follows.
// via same-name methods
myGSet.id();
myGSet.type();
myGSet.thing();
myGSet.groups();
// via the _gset method
myGSet._gset('id');
myGSet._gset('type');
myGSet._gset('thing');
myGSet._gset('groups');
-
args The
arguments
object.
Returns an object-literal containing non-critical invocation information.
The object returned has the following structure:
- gset The GSet instance.
- alias A string matching the scheme key used to invoke the current method.
- action A string reflecting the current execution phase: "custom", "get", "set", and "vet".
This is a convenience method, available to all functions, managed by a GSet instance. GSet wraps functions in a closure before execution, in order to pass secondary (or second-class) arguments. This information can be useful when branching logic within multi-purpose external routines.
var GVSroutine = function (value) {
var context = GSet.getContext(arguments);
if (context.action === 'get') {
return this.someProperty;
} else if (context.action === 'vet') {
return typeof v === 'string';
} else { // action must be "set"
this.someProperty = value;
return true;
}
};
myGSet = new GSet(obj,
{
setAndGet: [
GVSroutine,
GVSroutine,
GVSroutine
]
}
);
Note: To retrieve this information manually, target the indice of the arguments object of the calling function at arguments.callee.caller.arguments
. The order for this information is: [0] gset, [1] alias, [2] action.
GSet has no prototyped methods - rather closured methods, defined at instantiation. There are few reserved methods, but there names are reserved. Schemes with keys matching a reserved method name are ignored during compilation/instantiation.
- alias (Optional) The string identifier of the target map, or the GSet's signature object.
This method has several possible return values, depending on the given arguments.
-
When the only argument is valid alias, _gset returns the result of the get-behavior for the corresponding map or custom function.
-
When given multiple arguments and the first is a valid alias, _gset returns the result of the set-behavior for the corresponding map or custom function.
-
When the first argument matches the instance's signature, _gset returns the source object.
-
When no arguments are given, gset returns the instance's "charter" object.
This method throws an error for the following scenarios:
-
The first argument is not the instance signature nor valid alias
-
A valid map is targeted for an unsupported action; that is, a get-action is attempted with a set-only map, or set-action is attempted with a get-only map.
The _gset method is primarily designed to implement instance maps and route calls to custom functions. A get-action is triggered when a valid alias is passed. A set-action is triggered when a valid alias and subsequent arguments are passed. When the alias is for a custom function, _gset passes the additional arguments directly.
If an instance has a gate function, it is invoked before _gset calls the targeted get/vet/set or custom function. Should the gate function return false
, _gset stops executing and returns false as well.
When the _gset method is invoked without arguments, it returns a charter object. The charter is an object-literal, listing the compiled aliases for it's GSet instance. Each alias is paired with one of four indexes - an integer, representing the kind of method and supported actions.
- 2 refers to a custom method. (Only the GSet's author has insight as to it's functionality.)
- 1 refers to an alias that only supports get actions.
- 0 refers to an alias that supports set and get actions.
- -1 refers to an alias that only supports set actions.
Because GSet throws an error when invoking unsupported actions, verifying it's charter beforehand can avoid exceptions.
function changeUserName(user, newNameString) {
var charter = user._gset();
if (charter.name > -1) {
user.name(newNameString);
} else {
alert('The name of user "' + user.name() + '" may not be changed!');
}
}
Note: The charter is a cloned object with inherited members - thus hasOwnProperty
checks are not advised.