var Class = ( function( extending ) { // implementation left to reader var _privname = getRandomName(); var C = function( dfn ) { // extend from an empty base return C.extend( null, dfn ); }; C.extend = function( base, dfn ) { base = base || function() {}; // prevent ctor invocation extending = true; var ctor = function() { // do nothing if extending if ( extending ) { return; } // call "actual" constructor this.__construct && this.__construct.apply( this, arguments ); }; // public prototype ctor.prototype = new base(); ctor.prototype.constructor = ctor; // private prototype (read-only, // non-configurable, non-enumerable) Object.defineProperty( ctor, _privname, { value: {} } ); copyTo( ctor.prototype, ctor[ _privname ], dfn ); // done extending; clear flag to // ensure ctor can be invoked extending = false; return ctor; }; function copyTo( pub, priv, members ) { var hasOwn = Object.prototype .hasOwnProperty; for ( var member in members ) { if ( !hasOwn.call( members, member ) ) { continue; } // if prefixed with an underscore, // assign to private "prototype" var dest = ( member[ 0 ] === '_' ) ? priv : pub; dest[ member ] = wrap( members[ member ] ); } } function wrap( method ) { return function() { this.__priv = this.constructor[ _privname ]; var retval = method.apply( this, arguments ); this.__priv = undefined; return retval; }; } return C; } )( false ); // dummy implementation function getRandomName() { return '__privobj'; } var Foo = Class( { getValue: function() { return this.__priv._getPrivValue(); }, _getPrivValue: function() { return 'private'; } } ); var inst = new Foo(); inst.getValue(); // "private" inst._getPrivValue; // undefined inst.__priv; // undefined