我正在使用javascript和html5编写一个简单的平台游戏。我正在以OO方式使用javascript。为了继承工作我正在使用以下内容;
// 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];
}
};
为了这篇文章,请考虑以下示例;
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!');
根据我的理解,我希望看到一个horray警报框,因为C是C& C的实例。 B&答:我错了吗?或者我只是用错误的方法来检查?或者copyPrototype是否使用了instanceof运算符?
一如既往地感谢您花时间阅读本文!
肖。
答案 0 :(得分:16)
问题是copyPrototype
函数只将属性从构造函数原型复制到另一个,例如,最后,[[Prototype]]
的内容C.prototype
链接只指向Object.prototype
。
instC
的原型链和构造函数的原型看起来像这样:
[[Prototype]] A.prototype -------------->|-------------------| | | B.prototype -------------->| Object.prototype | ---> null | | C.prototype -------------->|-------------------| ^ | instC
instanceof
运算符遍历原型链,正如您所见,您的instC
对象仅在其原型链上C.prototype
和Object.prototype
。
通过将构造函数的原型设置为其“父”构造函数的对象实例,可以实现所需的目的,例如:
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!');
现在instC
对象的原型链看起来像这样:
--------------- --------------- --------------- instC --> | C.prototype | -----> | B.prototype | -----> | A.prototype | --------------- --------------- --------------- | V -------------------- | Object.prototype | -------------------- | V null
推荐文章:
答案 1 :(得分:6)
这些天你不应该需要.prototype = new Thing(),我想我迟到了,但是你可以在父的原型上使用Object.create然后覆盖方法你对覆盖感兴趣。一个例子:
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());
如果您在节点中运行此代码,您将获得:
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
不用担心构造函数的参数或任何这样的疯狂。
答案 2 :(得分:1)
好的,我找到了一个解决方案,它可以使instanceof函数保持工作,并允许我通过继承链传递构造函数参数。解决方案详述如下; https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Details_of_the_Object_Model - 我的班级结构现在看起来像这样;
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!
感谢CMS向我强调为什么这不起作用!!
你可以查看完整的项目(以及在编写本文时尚未看到这个全新的OO方法的旧版本)http://8weekgame.shawson.co.uk/ - 请查看我的最新帖子
答案 3 :(得分:1)
最近发现了John Resig(jQuery Guy!)的一个很好的OO javascript实现,我将在未来的项目中使用它; http://ejohn.org/blog/simple-javascript-inheritance/