actually your code is wrong because your snippet doesnt run, you should be doing the following: console.log( this.a );
and now, lets see how this works.
function foo() {
    console.log( this.a );
}
this will call this in the scope of the caller, so lets investigate our results.
so, you are setting a=2 globally, and then in the objects o.a = 3 and p.a=4
so:
calling  o.foo it will return 3 because this is pointing to o
calling  p.foo it will return 4 because this is pointing to p
BUT
calling  (p.foo = o.foo)(); it will return 2 because it is not pointing to any object, so it will take your scope (which is the global scope) and then it will return 2.
if you go with:
p.foo = o.foo
p.foo() //4
it will return 4 successfully because it is pointing to p.