src/topiarist.js
function extend(classDefinition, superclass, extraProperties) {
	var subclassName = className(classDefinition, 'Subclass');

	// Find the right classDefinition - either the one provided, a new one or the one from extraProperties.
	var extraPropertiesHasConstructor = typeof extraProperties !== 'undefined' &&
		extraProperties.hasOwnProperty('constructor') &&
		typeof extraProperties.constructor === 'function';

	if (classDefinition != null) {
		if (extraPropertiesHasConstructor && classDefinition !== extraProperties.constructor) {
			throw new Error(msg(ERROR_MESSAGES.TWO_CONSTRUCTORS, subclassName));
		}
	} else if (extraPropertiesHasConstructor) {
		classDefinition = extraProperties.constructor;
	} else {
		classDefinition = function() {
			superclass.apply(this, arguments);
		};
	}

	// check arguments
	assertArgumentOfType('function', classDefinition, ERROR_MESSAGES.SUBCLASS_NOT_CONSTRUCTOR);
	assertArgumentOfType('function', superclass, ERROR_MESSAGES.SUPERCLASS_NOT_CONSTRUCTOR, subclassName);
	assertNothingInObject(classDefinition.prototype, ERROR_MESSAGES.PROTOTYPE_NOT_CLEAN, subclassName);

	// copy class properties
	for (var staticPropertyName in superclass) {
		if (superclass.hasOwnProperty(staticPropertyName)) {
			// this is because we shouldn't copy nonenumerables, but removing enumerability isn't shimmable in ie8.
			// We need to make sure we don't inadvertently copy across any of the 'internal' fields we are using to
			//  keep track of things.
			if (internalUseNames.indexOf(staticPropertyName) >= 0) {
				continue;
			}

			classDefinition[staticPropertyName] = superclass[staticPropertyName];
		}
	}

	// create the superclass property on the subclass constructor
	Object.defineProperty(classDefinition, 'superclass', { enumerable: false, value: superclass });

	// create the prototype with a constructor function.
	classDefinition.prototype = Object.create(superclass.prototype, {
		'constructor': { enumerable: false,	value: classDefinition }
	});

	// copy everything from extra properties.
	if (extraProperties != null) {
		for (var property in extraProperties) {
			if (extraProperties.hasOwnProperty(property) && property !== 'constructor') {
				classDefinition.prototype[property] = extraProperties[property];
			}
		}
	}

	// this is purely to work around a bad ie8 shim, when ie8 is no longer needed it can be deleted.
	if (classDefinition.prototype.hasOwnProperty('__proto__')) {
		delete classDefinition.prototype['__proto__'];
	}

	clearAssignableCache(classDefinition, superclass);

	return classDefinition;
}
function extend(classDefinition, superclass, extraProperties) {
	var subclassName = className(classDefinition, 'Subclass');

	// Find the right classDefinition - either the one provided, a new one or the one from extraProperties.
	var extraPropertiesHasConstructor = typeof extraProperties !== 'undefined' &&
		extraProperties.hasOwnProperty('constructor') &&
		typeof extraProperties.constructor === 'function';

	if (classDefinition != null) {
		if (extraPropertiesHasConstructor && classDefinition !== extraProperties.constructor) {
			throw new Error(msg(ERROR_MESSAGES.TWO_CONSTRUCTORS, subclassName));
		}
	} else if (extraPropertiesHasConstructor) {
		classDefinition = extraProperties.constructor;
	} else {
		classDefinition = function() {
			superclass.apply(this, arguments);
		};
	}

	// check arguments
	assertArgumentOfType('function', classDefinition, ERROR_MESSAGES.SUBCLASS_NOT_CONSTRUCTOR);
	assertArgumentOfType('function', superclass, ERROR_MESSAGES.SUPERCLASS_NOT_CONSTRUCTOR, subclassName);
	assertNothingInObject(classDefinition.prototype, ERROR_MESSAGES.PROTOTYPE_NOT_CLEAN, subclassName);

	// copy class properties
	for (var staticPropertyName in superclass) {
		if (superclass.hasOwnProperty(staticPropertyName)) {
			// this is because we shouldn't copy nonenumerables, but removing enumerability isn't shimmable in ie8.
			// We need to make sure we don't inadvertently copy across any of the 'internal' fields we are using to
			//  keep track of things.
			if (internalUseNames.indexOf(staticPropertyName) >= 0) {
				continue;
			}

			classDefinition[staticPropertyName] = superclass[staticPropertyName];
		}
	}

	// create the superclass property on the subclass constructor
	Object.defineProperty(classDefinition, 'superclass', { enumerable: false, value: superclass });

	// create the prototype with a constructor function.
	classDefinition.prototype = Object.create(superclass.prototype, {
		'constructor': { enumerable: false,	value: classDefinition }
	});

	// copy everything from extra properties.
	if (extraProperties != null) {
		for (var property in extraProperties) {
			if (extraProperties.hasOwnProperty(property) && property !== 'constructor') {
				classDefinition.prototype[property] = extraProperties[property];
			}
		}
	}

	// this is purely to work around a bad ie8 shim, when ie8 is no longer needed it can be deleted.
	if (classDefinition.prototype.hasOwnProperty('__proto__')) {
		delete classDefinition.prototype['__proto__'];
	}

	clearAssignableCache(classDefinition, superclass);

	return classDefinition;
}
function extend ( classDefinition , superclass , extraProperties ) { var subclassName = className ( classDefinition , 'Subclass' ) ; // Find the right classDefinition - either the one provided, a new one or the one from extraProperties. var extraPropertiesHasConstructor = typeof extraProperties !== 'undefined' && extraProperties . hasOwnProperty ( 'constructor' ) && typeof extraProperties . constructor === 'function' ; if ( classDefinition != null ) { if ( extraPropertiesHasConstructor && classDefinition !== extraProperties . constructor ) { throw new Error ( msg ( ERROR_MESSAGES . TWO_CONSTRUCTORS , subclassName ) ) ; } } else if ( extraPropertiesHasConstructor ) { classDefinition = extraProperties . constructor ; } else { classDefinition = function ( ) { superclass . apply ( this , arguments ) ; } ; } // check arguments assertArgumentOfType ( 'function' , classDefinition , ERROR_MESSAGES . SUBCLASS_NOT_CONSTRUCTOR ) ; assertArgumentOfType ( 'function' , superclass , ERROR_MESSAGES . SUPERCLASS_NOT_CONSTRUCTOR , subclassName ) ; assertNothingInObject ( classDefinition . prototype , ERROR_MESSAGES . PROTOTYPE_NOT_CLEAN , subclassName ) ; // copy class properties for ( var staticPropertyName in superclass ) { if ( superclass . hasOwnProperty ( staticPropertyName ) ) { // this is because we shouldn't copy nonenumerables, but removing enumerability isn't shimmable in ie8. // We need to make sure we don't inadvertently copy across any of the 'internal' fields we are using to //  keep track of things. if ( internalUseNames . indexOf ( staticPropertyName ) >= 0 ) { continue ; } classDefinition [ staticPropertyName ] = superclass [ staticPropertyName ] ; } } // create the superclass property on the subclass constructor Object . defineProperty ( classDefinition , 'superclass' , { enumerable : false , value : superclass } ) ; // create the prototype with a constructor function. classDefinition . prototype = Object . create ( superclass . prototype , { 'constructor' : { enumerable : false , value : classDefinition } } ) ; // copy everything from extra properties. if ( extraProperties != null ) { for ( var property in extraProperties ) { if ( extraProperties . hasOwnProperty ( property ) && property !== 'constructor' ) { classDefinition . prototype [ property ] = extraProperties [ property ] ; } } } // this is purely to work around a bad ie8 shim, when ie8 is no longer needed it can be deleted. if ( classDefinition . prototype . hasOwnProperty ( '__proto__' ) ) { delete classDefinition . prototype [ '__proto__' ] ; } clearAssignableCache ( classDefinition , superclass ) ; return classDefinition ; }
Sets up the prototype chain for inheritance.

<p>As well as setting up the prototype chain, this also copies so called 'class' definitions from the superclass
to the subclass and makes sure that constructor will return the correct thing.</p>

@throws Error if the prototype has been modified before extend is called.

@memberOf topiarist
@param {?function} classDefinition The constructor of the subclass.
@param {!function} superclass The constructor of the superclass.
@param {?object} [extraProperties] An object of extra properties to add to the subclasses prototype.
Sets up the prototype chain for inheritance .