admin管理员组文章数量:1180551
I'm writing a simple platform game using javascript and html5. I'm using javascript in an OO manner. To get inheritance working i'm using the following;
// /
function copyPrototype(descendant, parent) {
var sConstructor = parent.toString();
var aMatch = sConstructor.match(/\s*function (.*)\(/);
if (aMatch != null) { descendant.prototype[aMatch[1]] = parent; }
for (var m in parent.prototype) {
descendant.prototype[m] = parent.prototype[m];
}
};
For the sake of this post consider the following example;
function A() {
this.Name = 'Class A'
}
A.prototype.PrintName = function () {
alert(this.Name);
}
function B() {
this.A();
}
copyPrototype(B, A);
function C() {
this.B();
}
copyPrototype(C, B);
var instC = new C();
if (instC instanceof A)
alert ('horray!');
As I understand it I would expect to see a horray alert box, because C is an instance of C & B & A. Am I wrong? Or am I just using the wrong method to check? Or has copyPrototype knackered the instanceof operator?
Thanks as always for taking the time to read this!
Shaw.
I'm writing a simple platform game using javascript and html5. I'm using javascript in an OO manner. To get inheritance working i'm using the following;
// http://www.sitepoint.com/blogs/2006/01/17/javascript-inheritance/
function copyPrototype(descendant, parent) {
var sConstructor = parent.toString();
var aMatch = sConstructor.match(/\s*function (.*)\(/);
if (aMatch != null) { descendant.prototype[aMatch[1]] = parent; }
for (var m in parent.prototype) {
descendant.prototype[m] = parent.prototype[m];
}
};
For the sake of this post consider the following example;
function A() {
this.Name = 'Class A'
}
A.prototype.PrintName = function () {
alert(this.Name);
}
function B() {
this.A();
}
copyPrototype(B, A);
function C() {
this.B();
}
copyPrototype(C, B);
var instC = new C();
if (instC instanceof A)
alert ('horray!');
As I understand it I would expect to see a horray alert box, because C is an instance of C & B & A. Am I wrong? Or am I just using the wrong method to check? Or has copyPrototype knackered the instanceof operator?
Thanks as always for taking the time to read this!
Shaw.
Share Improve this question edited Nov 20, 2013 at 11:47 Shawson asked Jun 30, 2010 at 0:17 ShawsonShawson 1,9882 gold badges25 silver badges40 bronze badges4 Answers
Reset to default 19The problem is that the copyPrototype
function only copies the properties from a constructors prototype to another one, for example, at the end, the intenal [[Prototype]]
link of C.prototype
simply points to Object.prototype
.
The prototype chain of instC
and constructor's prototypes look like this:
[[Prototype]] A.prototype -------------->|-------------------| | | B.prototype -------------->| Object.prototype | ---> null | | C.prototype -------------->|-------------------| ^ | instC
The instanceof
operator traverses the prototype chain, your instC
object, as you can see, will have on its prototype chain only C.prototype
and Object.prototype
.
You can achieve what you want by setting your constructor's prototypes to be object instances of their "parent" constructors, for example:
function A() {
this.Name = 'Class A'
}
A.prototype.PrintName = function () {
alert(this.Name);
}
function B() {
//..
}
B.prototype = new A();
B.prototype.constructor = B; // fix constructor property
function C() {
//..
}
C.prototype = new B();
C.prototype.constructor = C; // fix constructor property
var instC = new C();
if (instC instanceof A)
alert('horray!');
Now the prototype chain of the instC
object looks like this:
--------------- --------------- --------------- instC --> | C.prototype | -----> | B.prototype | -----> | A.prototype | --------------- --------------- --------------- | V -------------------- | Object.prototype | -------------------- | V null
Recommended article:
- Constructors considered mildly confusing
These days you shouldn't need .prototype = new Thing(), I think I'm late to the party but you can just use Object.create on the prototype of the parent and then override the methods you're interested in overriding. An example:
var IDataSource = function(){
throw new Error("Not implemented, interface only");
};
IDataSource.prototype.getData = function(){
throw new Error("Not implemented.");
};
var BasicDataSource = function(){};
BasicDataSource.prototype = Object.create(IDataSource.prototype);
BasicDataSource.prototype.getData = function(){
//[do some stuff, get some real data, return it]
return "bds data";
};
var MockDataSource = function(){};
MockDataSource.prototype = Object.create(IDataSource.prototype);
MockDataSource.prototype.getData = function(){
//[DONT DO some stuff return mock json]
return "mds data";
};
MockDataSource.prototype.getDataTwo = function(){
//[DONT DO some stuff return mock json]
return "mds data2";
};
var MockDataSource2 = function(){};
MockDataSource2.prototype = Object.create(MockDataSource.prototype);
var bds = new BasicDataSource();
console.log("bds is NOT MockDataSource:", bds instanceof MockDataSource);
console.log("bds is BasicDataSource:", bds instanceof BasicDataSource);
console.log("bds is an IDataSource:", bds instanceof IDataSource);
console.log("bds Data:", bds.getData());
var mds = new MockDataSource();
console.log("mds is MockDataSource:", mds instanceof MockDataSource);
console.log("mds is NOT a BasicDataSource:", mds instanceof BasicDataSource);
console.log("mds is an IDataSource:", mds instanceof IDataSource);
console.log("mds Data:", mds.getData());
console.log("mds Data2:",mds.getDataTwo());
var mds2 = new MockDataSource2();
console.log("mds2 is MockDataSource2:", mds2 instanceof MockDataSource2);
console.log("mds2 is MockDataSource:", mds2 instanceof MockDataSource);
console.log("mds2 is NOT a BasicDataSource:", mds2 instanceof BasicDataSource);
console.log("mds2 is an IDataSource:", mds2 instanceof IDataSource);
console.log("mds2 Data:", mds2.getData());
console.log("mds2 Data2:",mds2.getDataTwo());
If you run this code in node you will get:
bds is NOT MockDataSource: false
bds is BasicDataSource: true
bds is an IDataSource: true
bds Data: bds data
mds is MockDataSource: true
mds is NOT a BasicDataSource: false
mds is an IDataSource: true
mds Data: mds data
mds Data2: mds data2
mds2 is MockDataSource2: true
mds2 is MockDataSource: true
mds2 is NOT a BasicDataSource: false
mds2 is an IDataSource: true
mds2 Data: mds data
mds2 Data2: mds data2
No worry about parameters to constructors or any such craziness.
Ok I've found a solution which keeps the instanceof function working, as well as allowing me to pass constructor parameters through the inheritance chain. The solution is detailed here; https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Details_of_the_Object_Model - my class structure now looks like this;
function A(p) {
this.Position = p || new Vector2d(0,0);
}
function B(p) {
this.base = A;
this.base(p);
}
B.prototype = new A;
function C(p) {
this.base = B;
this.base(p);
}
C.prototype = new B;
if(C instanceof A)
alert (' it worked!! '); // you now see this alert box!
Thanks CMS for highlighting to me why this wasn't working!!
You can check out the full project (well an older build which, at time of writing has yet to see this new OO method put in the whole way through) up at http://8weekgame.shawson.co.uk/ - just check out my latest posts.
Recently found a nice implementation of OO javascript by John Resig (The jQuery Guy!) which I shall be using for future projects; http://ejohn.org/blog/simple-javascript-inheritance/
本文标签: oopJavascript inheritanceinstanceof not workingStack Overflow
版权声明:本文标题:oop - Javascript inheritance - instanceof not working? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738181476a2067498.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论