我正在尝试理解Javascript中的继承,但是这段代码(在Firebug中测试)并不像我期望的那样工作。我对此不了解什么?
var A = function(v){
this.v = v || 'foo';
}
A.prototype.shout = function(){ alert(this.v); }
var B = function(){};
B.prototype = new A;
var test = new B('bar')
test.shout() // returns 'foo'
我期待的是,当我分配test
时,属性this.v
设置为“bar”。据我所知,JS原型继承将B
的原型设置为A
意味着B
中的所有内容都会被覆盖。我希望它的构造函数被覆盖,并且调用new B('bar')
将使用参数“bar”执行A
的构造函数。
如果我的理解不正确,请有人纠正我。找到我想要做的解决方案也很好:
// constructors from above
B.prototype.yell = function(){ alert('hello world'); }
var test1 = new B('bar'), test2 = new B('spam'), test3 = new B('eggs');
...所以我创建的JS对象遵循与标准OOP类似的继承模式,因此B
将继承A
的构造函数和方法。
修改
阅读评论后,我认为更好的问题是如何用B
覆盖A
的构造函数?
答案 0 :(得分:2)
以下是构造函数。它在你打电话给新的时候运行。
var A = function(v){
this.v = v || 'foo';
}
在B构造函数中是function(){};所以你没有设置this.v
为了达到您正在尝试的结果,您应该遵循以下模式:
var A = function(v){
this.v = v || 'foo';
}
A.prototype.shout = function(){ alert(this.v); }
var B = function(v){
B.prototype.constructor.call(this,v); // here you call A constructor
};
B.prototype = new A;
var test = new B('bar')
test.shout() // returns 'bar
答案 1 :(得分:1)
设置
时var B = function(){};
你创建一个无参数构造函数B.然后当你做
B.prototype = new A;
您正在调用没有参数的A
构造函数(导致this.v = 'foo'
),然后导致B
的原型指向v
和{{1}但是,作为构造函数的shout
没有改变。通过在“B”的定义中添加一些参数可以看出这一点,例如:
B
应该产生'foobar'。
<强>附录:强> 我能想到的“复制”构造函数的最接近的方法实际上是创建具有一些第三方函数的两个构造函数并分配给A&amp; B.例子:
var B = function(x){this.v += x};
这不是真正的复制,正如您可以通过不同的默认值看到的那样,但它是确保两个定义保持同步的一种方法。
答案 2 :(得分:1)
不要将原型设置为A
的新实例,而是让B
的{{1}}委托最多prototype
的{{1}}。 Crockford称之为beget,它在Dojo中实现为A
。这是一个简单的函数,如下所示:
prototype
您可以使用它在原型之间创建此链接:
dojo.delegate
通过执行此操作,function delegate(o){
F = function(){}
F.prototype = o;
return new F;
}
构造函数永远不会被调用,并且永远不会设置var B = function(){}
B.prototype = delegate(A.prototype);
值。这将继承仅限于原型,而不是原型加构造函数。
答案 3 :(得分:0)
尝试
var test2 = new A('baz');
test2.shout(); //returns baz
我认为当你让'var B'成为一个新函数,而不是让它成为一个'新A'时,你会消灭'你'做'A'的'构造函数'。 我不确定如何调用原始文件来将test的v实例设置为'foo'。
答案 4 :(得分:-2)
如果不是试图让javascript像其他语言一样工作,你可以从中学到新的东西,并使用它就像javascript一样工作?