admin管理员组文章数量:1429840
Consider sample html code:
<head>
....
<script src="/js/MyClass.js"></script>
<script src="/js/extend.js"></script>
<script>
$(document).ready(function($) {
var $obj=new MyClass();
$obj.run();
});
</script>
</head>
<body>
MyClass.js file:
var MyClass=function()
{
this.run=function() {
alert("MyClass");
}
}
extend.js file:
MyClass.prototype.run=function() {
alert("Extend");
}
Why does this code alert "MyClass" instead of "Extend"? How to correctly rewrite (overload) class method?
Consider sample html code:
<head>
....
<script src="/js/MyClass.js"></script>
<script src="/js/extend.js"></script>
<script>
$(document).ready(function($) {
var $obj=new MyClass();
$obj.run();
});
</script>
</head>
<body>
MyClass.js file:
var MyClass=function()
{
this.run=function() {
alert("MyClass");
}
}
extend.js file:
MyClass.prototype.run=function() {
alert("Extend");
}
Why does this code alert "MyClass" instead of "Extend"? How to correctly rewrite (overload) class method?
Share Improve this question edited Oct 9, 2013 at 10:39 opalenzuela 3,17122 silver badges42 bronze badges asked Oct 9, 2013 at 10:34 Mike DoeMike Doe 17.7k11 gold badges73 silver badges95 bronze badges3 Answers
Reset to default 5It'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 es 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 pare 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...
The prototype is only used when the object itself does not have the property already.
In your case, you put run
on the object itself, so that is what run
will resolve to.
In a way, your MyClass is overriding its own prototype.
Maybe you want
var MyClass=function(){};
MyClass.prototype.run = function() {
alert("MyClass");
}
var overridden = new MyClass();
overridden.run = function() {
alert("Extend");
}
That would be an instance with a different method than its prototype.
Or you could chain prototypes to simulate a class hierarchy.
Your MyClass constructor is overriding the prototype. The following code will alert "MyClass", "Extended" and "Overriden" each in turn. The last alert shows that changing the instance's function does not change the prototype's function.
var MyClass=function()
{
this.run();
MyClass.prototype.run = function() { alert( "Extended" ) };
this.run();
this.run=function() {
alert("Overriden");
};
this.run();
};
MyClass.prototype.run = function() { alert( "MyClass" ); };
var myinstance = new MyClass();
alert( myinstance.run === MyClass.prototype.run );
本文标签: Method overload in JavaScriptStack Overflow
版权声明:本文标题:Method overload in JavaScript - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745476087a2659970.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论