2012-04-21 63 views
0

我写这段代码模拟OOP继承和调用基类中的JavaScript和它的作品:如何使用原型避免在javascript中复制函数?

function Animal(name,age) 
    { 
    this._name = name; 
    this.setName = function (name) { this._name = name } 
    this.getName = function() { return this._name } 
    } 

    function Cat(name,age) 
    { 
    Animal.call(this,name,age); // call baseclass constructor 
    this.getName = function() { return Cat.prototype.getName.call(this)+", a cat" } 
    } 
    Cat.prototype = new Animal(); // will create the baseclass structure 

    /// ***** actual execution ***** 
    var puss = new Cat("Puss",3); 
    var cheshire = new Cat("Cheshire",10); 
    // do some actions 
    console.log (puss.getName()); 
    // change cat's name 
    puss.setName("Puss in boots"); 
    alert ("new name -->"+puss.getName()); 

的问题是,对于每个实例“新猫()”中的“的getName”和“的setName”功能被复制。 我已经阅读了很多关于原型设计的文章,但都没有提到调用基类功能的问题。

+0

这是JavaScript的工作原理!每个新创建的对象都具有从原型复制的所有属性。这是正常行为,不是问题。你想要什么? – freakish 2012-04-21 14:52:10

回答

1

你应该分配方法给函数的原型,例如,

function Animal(name, age) { 
    this._name = name; 
    this._age = age; 
} 
Animal.prototype.getName = function() { return this._name; } 
Animal.prototype.setName = function (value) { this._name = value; } 

function Cat(name, age) { 
    Animal.call(this, name, age); 
} 
Cat.prototype = new Animal(); 
Cat.prototype.getName = function() { 
    return Animal.prototype.getName.call(this) + ", a cat"; 
} 
+0

有没有一种简单的方法来防止Animal的构造函数运行两次? – 2012-04-21 17:11:00

+0

我不明白你的意思。它是如何运行两次? – chuckj 2012-04-21 22:26:58

+1

@尼尔。就在这里。在ES5中,您可以使用[Object.create](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/create)(在不支持它的浏览器中,您可以使用写入的填充链接)。所以你将有:'Cat.prototype = Object.create(Animal.prototype);' – ZER0 2012-04-22 00:57:44

0

http://phrogz.net/js/classes/OOPinJS2.html

Javascript does not have any sort of 'super' property, which would point to its parent class. Instead, you use the call() method of a Function object, which allows you to run a function using a different object as context for it. If you needed to pass parameters to this function, they would go after the 'this'.

在你的情况下,它适用于功能“办法”是相同的,所以你可以这样做:

Animal.prototype.setName.call(this, name); 
+0

给出TypeError:Animal.prototype.getName是未定义的 – 2012-04-21 15:03:32

+0

对不起,我在发布后稍微改变了它。部分问题将出现在您在Animal函数中定义的setName和getName方法中。这些也需要成为原型。我鼓励你看看我提供的链接,因为他涵盖了所有这些。 – 2012-04-21 15:04:45

0

您是否在寻找__proto__存储原型的数据? https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/Proto

如果你做一个console.log(puss.__proto__.getName)你会得到什么似乎是“基类”功能,但我不知道这是如何跨浏览器。

+0

'__proto__'在所有浏览器中都不可访问,应该避免。 – 2012-04-21 15:08:57

+0

@FelixKling:直到/除非[标准化](http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts)... *“添加了B.3.1节并指定了'__proto__'特性。”* – 2012-04-21 15:12:28