1
0
Fork 0

Returning 'this' from a method will now return the object instance, not the internal property object

closure/master
Mike Gerwitz 2011-03-10 12:19:39 -05:00
parent 22220cd2da
commit 7427958ec0
2 changed files with 46 additions and 3 deletions

View File

@ -314,6 +314,7 @@ function overrideMethod( super_method, new_method, instCallback )
// __super property // __super property
var override = null; var override = null;
// are we overriding?
if ( new_method ) if ( new_method )
{ {
override = function() override = function()
@ -330,11 +331,25 @@ function overrideMethod( super_method, new_method, instCallback )
} }
else else
{ {
// we are defining a new method
override = function() override = function()
{ {
return super_method.apply( var context = instCallback( this ) || this,
( instCallback( this ) || this ), arguments retval = undefined
); ;
// invoke the method
retval = super_method.apply( context, arguments );
// if the value returned from the method was the context that we
// passed in, return the actual instance (to ensure we do not break
// encapsulation)
if ( retval === context )
{
return this;
}
return retval;
}; };
} }

View File

@ -45,6 +45,7 @@ var common = require( './common' ),
'protected protf': protf, 'protected protf': protf,
'private privf': privf, 'private privf': privf,
'public getProp': function( name ) 'public getProp': function( name )
{ {
// return property, allowing us to break encapsulation for // return property, allowing us to break encapsulation for
@ -60,6 +61,12 @@ var common = require( './common' ),
{ {
this[ name ] = value; this[ name ] = value;
}, },
'public getSelf': function()
{
return this;
},
}), }),
// instance of Foo // instance of Foo
@ -308,3 +315,24 @@ var common = require( './common' ),
); );
} )(); } )();
/**
* When a method is called, 'this' is bound to the property object containing
* private and protected members. Returning 'this' would therefore be a very bad
* thing. Not only would it break encapsulation, but it would likely have other
* problems down the road.
*
* Therefore, we have to check the return value of the method. If the return
* value is the property object that it was bound to, we need to replace the
* return value with the actual class instance. This allows us to transparently
* enforce encapsulation. How sweet is that?
*/
( function testReturningSelfFromMethodShouldReturnInstanceNotPropObj()
{
assert.deepEqual(
foo.getSelf(),
foo,
"Returning 'this' from a method should return instance of self"
);
} )();