diff --git a/lib/class.js b/lib/class.js index cfae254..9933fdf 100644 --- a/lib/class.js +++ b/lib/class.js @@ -790,21 +790,19 @@ function attachPropInit( prototype, properties, members ) parent_init.call( this, true ); } + // this will return our property proxy, if supported by our environment, + // otherwise just a normal object with everything merged in var inst_props = propobj.createPropProxy( this, class_instance[ this.__iid ], properties[ 'public' ] ); - // use whatever was returned by the property proxy (which may not be a - // proxy, depending on JS engine support) - class_instance[ this.__iid ] = inst_props; - // if we're inheriting, perform a setup that doesn't include everything // that we don't want (e.g. private properties) var setup = ( inherit ) ? propobj.setupInherited : propobj.setup ; - setup( inst_props, properties, members ); + class_instance[ this.__iid ] = setup( inst_props, properties, members ); }); } diff --git a/lib/propobj.js b/lib/propobj.js index c60d431..5e25e91 100644 --- a/lib/propobj.js +++ b/lib/propobj.js @@ -39,7 +39,7 @@ var util = require( './util' ), * @param {Object} properties properties to copy * @param {Object=} methods methods to copy * - * @return {undefined} + * @return {Object} dest */ exports.setupInherited = function( dest, properties, methods ) { @@ -47,27 +47,41 @@ exports.setupInherited = function( dest, properties, methods ) // ensure we're not sharing references to prototype values doSetup( dest, properties[ 'public' ] ); doSetup( dest, properties[ 'protected' ], methods[ 'protected'] ); + + return dest; }; /** * Sets up properties (non-inheriting) * - * This includes all members (including private). + * This includes all members (including private). Private members will be set up + * in a separate object, so that they can be easily removed from the mix. That + * object will include the destination object in the prototype, so that the + * access should be transparent. This object is returned. * * @param {Object} dest destination object * @param {Object} properties properties to copy * @param {Object=} methods methods to copy * - * @return {undefined} + * @return {Object} object containing private members and dest as prototype */ exports.setup = function( dest, properties, methods ) { + // this constructor is an extra layer atop of the destination object, which + // will contain the private methods + var obj_ctor = function() {}; + obj_ctor.prototype = dest; + + var obj = new obj_ctor(); + // first, set up the public and protected members exports.setupInherited( dest, properties, methods ); // then add the private parts - doSetup( dest, properties[ 'private' ], methods[ 'private' ] ); + doSetup( obj, properties[ 'private' ], methods[ 'private' ] ); + + return obj; }; diff --git a/test/perf/perf-class-invoke-method.js b/test/perf/perf-class-invoke-method.js index bc8b5b8..2a97355 100644 --- a/test/perf/perf-class-invoke-method.js +++ b/test/perf/perf-class-invoke-method.js @@ -13,6 +13,10 @@ * - Protected and private methods internally should be accessed fairly * quickly since, like public methods externally, they are first on the * prototype chain. + * - Protected members will be accessed more slowly than private members, + * because they are one step lower on the prototype chain. Future versions + * will remove this performance hit if the Class contains no private + * members. * * Copyright (C) 2010 Mike Gerwitz *