var Class = ( function( extending ) { 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 ); }; ctor.prototype = new base(); ctor.prototype.constructor = ctor; copyTo( ctor.prototype, dfn ); // done extending; clear flag to // ensure ctor can be invoked extending = false; return ctor; }; function copyTo( dest, members ) { var hasOwn = Object.prototype .hasOwnProperty; for ( var member in members ) { if ( !hasOwn.call( members, member ) ) { continue; } dest[ member ] = members[ member ]; } } return C; } )( false ); var Foo = Class( { __construct: function( name ) { if ( !name ) { throw TypeError( "Name required" ); } this._name = ''+( name ); }, getName: function() { return this._name; } } ); var SubFoo = Class.extend( Foo, { setName: function( name ) { this._name = ''+( name ); } } ); var myfoo = new Foo( "Foo" ), mysub = new SubFoo( "SubFoo" ); myfoo.getName(); // "Foo" mysub.getName(); // "SubFoo" mysub.setName( "New Name" ); mysub.getName(); // "New Name" // parent Foo does not define setName() myfoo.setName( "Error" ); // TypeError // our name will be required, since we // are not extending new Foo(); // TypeError