cortex
Property Encapsulation
In JavaScript it is not possible to create properties that have limited or controlled accessibility. It is possible to create non-enumerable and non-writable properties, but still they can be discovered and accessed. Usually so called "closure capturing" is used to encapsulate such properties in lexical scope:
| 1 2 3 4 5 6 | functionFoo() {  var_secret = 'secret';  this.hello = functionhello() {    return'Hello '+ _secret;  }} | 
This provides desired result, but has side effect of degrading code readability, especially with object-oriented programs. Another disadvantage with this pattern is that there is no immediate solution for inheriting access to the privates (illustrated by the following example):
| 1 2 3 4 5 6 7 8 9 | functionDerived() {  this.hello = functionhello() {    return_secret;  }  this.bye = functionbye() {    return_secret;  }}Derived.prototype = Object.create(Foo.prototype); | 
Facade Objects
Alternatively constructor can returned facade objects - proxies to the instance's public properties:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | functionFoo() {  varfoo = Object.create(Foo.prototype);  return{    bar: foo.hello.bind(foo);  }}Foo.prototype._secret = 'secret';Foo.prototype.hello = functionhello() {  return'Hello '+ this._secret;}functionDerived() {  varderived = Object.create(Derived.prototype);  return{    bar: derived.hello.bind(derived);    bye: derived.bye.bind(derived);  }}Derived.prototype = Object.create(Foo.prototype);Derived.prototype.bye = functionbye() {  return'Bye '+ this._secret;}; | 
While this solution solves given issue and provides proper encapsulation for both own and inherited private properties, it does not addresses following:
- Privates defined on the prototypecan be compromised, since they are accessible through the constructor (Foo.prototype._secret).
- Behavior of instanceofis broken, sincenew Derived() instanceof Derivedis going to evaluate tofalse.
Tamper Proofing with Property Descriptor Maps
In ES5 new property descriptor maps were introduced, which can be used as a
building blocks for defining reusable peace of functionality. To some degree
they are similar to a prototype objects, and can be used so to define pieces
of functionality that is considered to be private (In contrast to prototype
they are not exposed by default).
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | functionFoo() {  varfoo = Object.create(Foo.prototype, FooDescriptor);  varfacade = Object.create(Foo.prototype);  facade.hello = foo.hello.bind(foo);  returnfacade;}Foo.prototype.hello = functionhello() {  return'Hello '+ this._secret;}varFooDescriptor = {  _secret: { value: 'secret'};}functionDerived() {  varderived = Object.create(Derived.prototype, DerivedDescriptor);  varfacade = Object.create(Derived.prototype);  facade.hello = derived.hello.bind(derived);  facade.bye = derived.bye.bind(derived);  returnfacade;}Derived.prototype = Object.create(Foo.prototype);Derived.prototype.bye = functionbye() {  return'Bye '+ this._secret;};DerivedDescriptor = {};Object.keys(FooDescriptor).forEach(function(key) {  DerivedDescriptor[key] = FooDescriptor[key];}); | 
Cortex Objects
Last approach solves all of the concerns, but adds complexity, verbosity
and decreases code readability. Combination of Cortex's and Trait's
will gracefully solve all these issues and keep code clean:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | varCortex = require('cortex').Cortex;varTrait = require('light-traits').Trait;varFooTrait = Trait({  _secret: 'secret',  hello: functionhello() {    return'Hello '+ this._secret;  }});functionFoo() {  returnCortex(FooTrait.create(Foo.prototype));}varDerivedTrait = Trait.compose(FooTrait, Trait({  bye: functionbye() {    return'Bye '+ this._secret;  }}));functionDerived() {  varderived = DerivedTrait.create(Derived.prototype);  returnCortex(derived);} | 
Function Cortex takes any object and returns a proxy for its public
properties. By default properties are considered to be public if they don't
start with "_", but default behavior can be overridden if needed, by passing
array of public property names as a second argument.
Gotchas
Cortex is just a utility function to create a proxy object, and it does not
solve the prototype-related issues highlighted earlier, but since traits make
use of property descriptor maps instead of prototypes, there aren't any
issues with using Cortex to wrap objects created from traits.
If you want to use Cortex with an object that uses a prototype chain,
however, you should either make sure you don't have any private properties
in the prototype chain or pass the optional third prototype argument.
In the latter case, the returned proxy will inherit from the given prototype,
and the prototype chain of the wrapped object will be inaccessible.
However, note that the behavior of the instanceof operator will vary,
as proxy instanceof Constructor will return false even if the Constructor
function's prototype is in the wrapped object's prototype chain.
