javascript游戏关卡继承

时间:2013-07-11 08:30:35

标签: javascript

我正在将我在Flash / AS3.0中设计的游戏重写为javascript,并且在学习课程时难以绕过原型。我已经阅读了大量有关它的信息,我仍然不太确定如何将其应用于这种情况。

所以...在我的AS3.0项目中,我有一个关卡类,它具有游戏各个层面发生的内容,Enter_Frame功能等。然后我将每个级别的类扩展为特定级别项目放置,地形细节等细节...所以我的问题是如何最有效和“正确”的方式来做到这一点。

现在我有两个功能:

function level() {
//generic level functionality
}

function level1() {
//level1 specific functionality
}

然后,正如我读过的那样,我应该设置

level1.prototype = new level();

但我发现这会在运行时执行level函数中的所有内容,这是我不想要的。理想情况下,我想要一个开始按钮来实例化level1,而level1则拥有level的属性和方法 - 如果可能的话,在发生这种情况时执行level1和level的构造函数中的所有内容......是否可能?

我确定这很明显,但我似乎无法点击,抱歉,如果我问一个愚蠢的问题。 非常感谢任何提前帮助。

4 个答案:

答案 0 :(得分:2)

为避免在建立继承时执行构造函数,可以使用Object.create()

level1.prototype = Object.create(level.prototype);

但是,对于“ chain ”构造函数调用,您还需要level中的call level1

function level1() {
    level.call(this);

    // ...
}

使用call可以传递上下文(this),这样两个构造函数都可以使用相同的对象。

答案 1 :(得分:0)

您要实现的是JavaScript中的某种面向对象解决方案。看看at this blog post,它详细描述了它,并给出了一个很好的例子。 : - )

答案 2 :(得分:0)

可以使用Obj.call(this,args)调用父构造函数。代码还应保留level1的原型level1.prototype = new level()的赋值,因为这将创建两个对象之间关系的继承。

function level(config) {
    if(config){
       this.someProperty = config.prop;
       alert("Level constructor");
       alert("Level property " + this.someProperty);
    }
}

function level1(config) {
   level.call(this, config);
   this.someProperty2 = config.prop2;
   alert("Level1 Construtor");
   alert("Leve1 property " + this.someProperty2);
   alert("Level1 using prop from level " + this.someProperty);
}

level1.prototype = new level();

var myLevel = new level1({
    prop: "Test prop",
    prop2: "Test prop2"
});

工作示例 http://jsfiddle.net/kz2Xc/1/

答案 3 :(得分:0)

用户JonathanLonowski已经回答了您在设置inheritanc时如何避免调用构造的问题。但我也把你的问题看成是一个关于如何在JavaScript中使用inhertance的一般性问题。所以我试图解释这个话题:

当涉及到继承时,你基本上想要做的是增强原型链。

那么,原型链是什么?

当您使用obj.prop请求对象的属性时,如果对象obj具有此类属性,则JavaScript首先检查。如果没有,它会检查该对象的原型是否具有这样的属性。如果没有,它会检查原型的原型是否具有这样的属性等等。

当您通过编写obj = new B()创建具有构造函数的新对象时,原型链看起来如下:

obj -> B.prototype -> Object -> null

继承如何与原型链一起使用

如果您希望B个对象从A类型的对象继承,您希望原型链看起来像这样:

obj -> B.prototype -> A.prototype -> Object -> null

为实现这一目标,您需要在B.prototype之后“打破”原型链,然后插入A的完整原型链。或者换句话说,您希望将B.prototype设置为指向A.prototype

你可以像以前一样做到这一点:

B.prototype = new A();

现在为什么这样做? new A()创建的对象具有以下原型链:

objA -> B.prototype -> Object -> null

如果使用此对象覆盖B.prototype,则类型为B的对象的原型链如下所示:

objB -> objA -> A.prototype -> Object -> null

如你所见,它有效。只需覆盖B.prototype,您就会丢失一些属性,例如constructor属性。因此,如果您尝试使用constructor获取B类型的对象objB.constructor,它首先查找对象本身但找不到它,然后查看{{1}并且找不到它,然后查看objA并查找A.prototype,这是错误的。虽然您经常不需要A属性,但在覆盖constructor之后再次设置它是一种良好的做法:

B.prototype

现在,您的方式只是实现原型链链接的一种方式。 JonathanLonowski的解决方案是另一个,确实是更好的解决方案,因为它不会调用函数B.prototype = new A(); B.prototype.constructor = B; 。它创建一个空对象,其原型链与A类型的对象相同:

A

另一种解决方案是不覆盖(empty object) -> A.prototype -> Object -> null ,但修改它只是指向B.prototype而不是A.prototype。并非每个浏览器都支持此功能,但在某些浏览器中,您可以通过设置Object属性来实现此目的:

__proto__

这将产生以下原型链:

B.prototype.__proto__ = A.prototype;

请注意,我在这里和那里简单地说它,但我认为这应该让你知道它是如何工作的。最基本的事情是原型设计。现在,从技术上讲,只有一个真正的原型属性,每个对象都具有内部obj -> B.prototype -> A.prototype -> Object -> null 属性。您无法直接在JavaScript中访问它,但是您可以[[prototype]].prototype设置它并在特定条件下对其进行操作。