It's all got to do with how JS resolves expressions like <object>.<property/function>. I've previously explained this in detail, but here's the schematic run-down applied to your case:
[ MyClass.run ]<=========================================================\ \
MyClass[run] ===> JS checks instance for property run | |
/\ || | |
|| || --> property found @instance, resolve value------------------------------| |
|| || | |
|| ===========> MyClass.prototype.run could not be found? check prototype | |
|| || | |
|| ||--> OR property found @MyClass.prototype, return---------------------| |
|| || | |
|| ==========> Object.prototype.run: not found check prototype? | |
|| || | |
|| ||--> property found @Object.prototype, return---------------------|-|
|| || |=|
|| =======> chech prototype of Object.prototype -> undefined~~~~~~~~~~|X|
|| \ /
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< TypeError can't read property run of undefined
This is All of the places JS can check for the run property. Because your constructor function defines a run property on the instance (this.run = function(){};), the lookup never goes past the first step: "JS checks instance for property run".
The prototype-chain never comes into play.
You ask if, and how, it might be possible to overload JS methods. The short answer is: It isn't, not really. Overloading is a valid OOP technique, that is very handy in traditional, class-based OO models. JS doesn't play that way, it uses a prototypal model instead. Trying to force the prototypal system to work like a traditional OO language is possible (owing to the flexability of the prototypal system), but it requires too much effort to keep up, and often just isn't worth it.
You could compare it to using a regular saloon/sedan car to plow a field. At first, you may be able to, but it won't take long before you get stuck, and have to call on a tractor to tow you out of the field.
If you still want to give it a try, here's how:
function MyClass()
{
this.run = function()
{
console.log('child method');
var backup = this.run;//store reference to instance property
delete this.run;//delete instance property
this.run();//call again
//but now, the instance property is missing, JS will use the prototype
this.run = backup;//restore instance property
};
}
MyClass.prototype.run = function()
{
console.log('prototype run method');
};
var foo = new MyClass;
foo.run();
//logs:
//child method
//prototype run method
You might find it useful to take a look here, it's the previous answer in which I explained JS's way of resolving expressions a bit more detailed. At the bottom of my answer there, I've also added some more links on the matter, might be worth while looking at them, too...