1
0
Fork 0

[*] Previous commit (property cloning per instance) now applied to subtypes as well

closure/master
Mike Gerwitz 2010-12-16 23:37:18 -05:00
parent fe853b505b
commit 591434b82f
2 changed files with 64 additions and 10 deletions

View File

@ -109,9 +109,11 @@ var extend = ( function( extending )
prototype.parent = base.prototype;
// set up the new class
var new_class = create_ctor( result_data, properties );
var new_class = create_ctor( result_data );
setup_props( new_class, result_data );
attach_prop_init( prototype, properties );
new_class.prototype = prototype;
new_class.constructor = new_class;
@ -143,15 +145,7 @@ var extend = ( function( extending )
{
return function()
{
// initialize each of the properties for this instance to
// ensure we're not sharing prototype values
var value;
for ( prop in properties )
{
// initialize the value with a clone to ensure that they do
// not share references (and therefore, data)
this[ prop ] = util.clone( properties[ prop ] );
}
this.__initProps();
// call the constructor, if one was provided
if ( this.__construct instanceof Function )
@ -190,6 +184,47 @@ function setup_props( func, class_data )
}
/**
* Attaches __propInit() method to the class prototype
*
* The __propInit() method will initialize class properties for that instance,
* ensuring that their data is not shared with other instances (this is not a
* problem with primitive data types).
*
* The __propInit() method will also initialize any parent properties
* (recursive) to ensure that subtypes do not have a referencing issue, and
* subtype properties take precedence over those of the parent.
*
* @param {Object} prototype prototype to attach method to
* @param {Object} properties properties to initialize
*
* @return {undefined}
*/
function attach_prop_init( prototype, properties )
{
util.defineSecureProp( prototype, '__initProps', function()
{
// first initialize the parent's properties, so that ours will overwrite
// them
var parent_init = prototype.parent.__initProps;
if ( parent_init instanceof Function )
{
parent_init.call( this );
}
// initialize each of the properties for this instance to
// ensure we're not sharing prototype values
var value;
for ( prop in properties )
{
// initialize the value with a clone to ensure that they do
// not share references (and therefore, data)
this[ prop ] = util.clone( properties[ prop ] );
}
});
}
/**
* Attaches isAbstract() method to the class
*

View File

@ -166,3 +166,22 @@ assert.ok(
"Multiple instances of the same class do not share object references"
);
var arr_val = 1;
var SubAnotherFoo = AnotherFoo.extend(
{
arr: [ arr_val ],
});
var SubObj1 = new SubAnotherFoo(),
SubObj2 = new SubAnotherFoo();
assert.ok(
( ( SubObj1.arr !== SubObj2.arr ) && ( SubObj1.obj !== SubObj2.obj ) ),
"Instances of subtypes do not share property references"
);
assert.ok(
( ( SubObj1.arr[ 0 ] === arr_val ) && ( SubObj2.arr[ 0 ] === arr_val ) ),
"Subtypes can override parent property values"
);