适当的原型继承

时间:2013-04-15 16:49:54

标签: javascript inheritance prototype prototypal

所以我真的在互联网上看了很多不同的方法来设置javascript中的原型继承。

其中一些人使用call() 他们中的一些人使用这个sytnax:var rabbit.prototype = new Animal 其中一些在更改原型后更改了构造函数,有些则没有 有些设置了一个有助于设置继承的小功能。

有人可以对此有所了解吗?有很多关于这个的帖子,但好的帖子已经超过2年了,它们在我的脑海里引起了很大的混乱。
我想一劳永逸地知道如何在javascript中正确设置原型继承。

如果简单就更好了!

3 个答案:

答案 0 :(得分:4)

实现了几种不同的javascript继承方式,这最终是我想要为浏览器RPG构建javascript游戏引擎的时候:

玩家基类:

function Player(name, type, gender, experience, avatar){
    this.name = name;
    this.type = type;
    this.gender = gender;
    this.experience = experience;
    this.avatar = avatar;

    this.stats ={//getter, setter}
    //lots more code
}

向玩家类添加方法

Player.prototype.decrease_life = function(decrement){} 
//note that the keyword this in the decrease_life function will 
//refer to the player that the method is called on.

现在继承玩家类:

function Mage(name, type, gender, exp, avatar){
    Player.apply(this, [name,type,gender,exp,avatar]); 
    //apply allows you to specify what the keyword 
    //this refers to in the Player super class.
}
Mage.prototype = new Player;

最后我们创建一个玩家:

current_player =  new Mage(name,type,gender,0,avatar);

现在允许我们这样做:

current_player.decrease_life(20); //The mage loses 20 life!

或者这样做:

current_player.stats.get(); 
//returns the mages stats, it does that because we used apply, and 
//this.stats in the player class is referring to our mage now

正如其他人所说,javascript继承没有最佳实践。我发现上面最接近的模仿了你如何期望继承在Java或C ++中工作,它们具有更多典型的继承结构。

答案 1 :(得分:2)

关于原型继承的重要一点是,你是从对象继承而不是从类继承。所以我的想法是tomsBankAccount继承bankAccount,这可能是通过基于类的语言中的即时性来完成的。如果你想要一个'类'的'实例',那就可以通过实现公共特征的对象完成,它是任何需要这些特征的对象的原型。

这是一个未经测试和错误的具体示例。但这是我错的原因。

var bankAccount = {
    withdraw: function(amount) { this.balance -= amount },
    deposit: function(amount) { this.balance += amount }
}

var account1 = {
    balance: 50
}

account1.prototype = bankAccount
account1.deposit(100)
alert(account1.balance)  // Displays 150

因此,对象有自己的东西,如balance字段,但将常用功能委托给bankAccount对象。所以继承的等价物就是决定一个普通案例对象和原型。

实际上,上面的代码已经破了。 JavaScript不会让您只是原型化任何旧对象,或者至少较旧 JavaScript不会。它强制原型化只能从constructor functions返回的对象完成,这些对象在您调用它们时在JavaScript中具有特殊语法,即new关键字。

您可能已经看到类似这样的代码(再次,未经测试):

function BankAccount(balance) {
    this.balance = balance
    this.withdraw = function(amount) { this.balance -= amount }
    this.deposit = function(amount) { this.balance += amount }
}

var account1 = new BankAccount(50)
account1.deposit(100)
alert(account1.balance)  // Same result as last time

你还会注意到他们以大写字母开头。就是这样,基本上。 this很奇怪 - 它带有对函数所包含的对象的引用。因此,带有deposit方法的对象也会带有balance属性,这就是我们可以通过方法balance访问this的原因。

但上面的代码不是惯用的JavaScript。一旦掌握了它,有些事情需要记住。例如,上面重新分配了每个对象构造的新方法,这显然不是很快。通过将方法分配给函数构造函数的原型来解决这个问题。还可以通过JavaScript的闭包来“私有化”属性。

你可能会怀疑JavaScript类似于Java的符号表示完全是误导,因为它在下面是如此不同......我同意。

答案 2 :(得分:1)

没有真正统一的'最佳方式'来做到这一点。来自2岁的“好答案”仍然具有相关性(如果它们很好,我个人会放弃任何试图模仿课程的东西),因为javascript(EcmaScript)已经很久了(十多年)。

call用于传递this的内容。

至于原型继承:我真的很喜欢YUI剧院的'crockford on javascript'。 您想要观看“Act III: function the ultimate

最简单的设置原型的方法是:
objectIdentifier.prototype.methodIdentifier = function(args){ /* your code*/ }

有许多不同的“构造模式”,其中大部分都在特定的情况下使用。考虑一段代码将要做什么以及经常如何使用它通常是一个好主意。你也想看看像JQuery这样的流行图书馆,看看他们的模式。

希望这有帮助!