【发布时间】:2013-08-12 02:25:49
【问题描述】:
在我了解Object.create() 之前,当我对原型的了解甚至比现在还少时,我编写了一些看起来像这样的代码:
var Foo = function() {
this.report('Foo');
};
Foo.report = function(i) { // You read that right; it's not 'Foo.prototype.report'
alert('report: ' + i);
};
var Bar = function() {
this.report('Bar');
};
Bar.prototype = Foo; // Right; it's not 'new Foo()'
var b = new Bar();
b.report('b');
奇怪的是,这确实有效,或者至少它按我预期的方式工作:它会提醒“Bar”,然后是“b”。但是如果我尝试直接使用Foo(),它会失败:
var f = new Foo();
f.report('f');
浏览器告诉我该对象没有方法report()。为什么它适用于'b'而不适用于'f'?此外,如果我设置Bar.prototype = new Foo()(不将Foo.report 更改为Foo.prototype.report),那么'b' 再次起作用,但浏览器说'f' 没有report() 方法。但是,如果我将report() 添加到Foo.prototype 而不是仅仅将其添加到Foo,那么一切都会完美运行。当然,如果我设置Bar.prototype = Object.create(Foo.prototype),一切正常。但是滥用部分工作和失败的方式让我完全困惑。有人可以帮助我准确了解我做这些事情时发生了什么吗?具体来说,什么时候发生:
- 我将一个函数添加到
Foo,而不是添加到Foo.prototype - 我将
Bar.prototype设置为Foo,而不是设置为new Foo()或Object.create(...)
Resig 在Slide 76 中接近这一点,但他没有解释。我知道这不是使用原型的方式,但我觉得理解这种行为将对 js 原型设计有所启发。我以为我明白了!
【问题讨论】:
-
您在 constructor
Foo上设置属性,而不是在 instances 上设置属性,这正是设置prototype所做的。当您将Bar.prototype设置为Foo时,将引用Foo构造函数的report属性 -
@Ian 所以
Foo.report = ...和Foo.report.constructor = ...一样吗? -
我不这么认为。也许我不应该说“构造函数”。我所说的“构造函数”的意思只是它可以用作通过使用
new创建实例(至少是您设置它的方式以及您通常期望的方式)。Foo只是一个对象(一个函数),它具有属性。但是当您使用new Foo()时,这些属性不会复制到实例中。复制的属性来自Foo.prototype。我所说的“复制”实际上是指“参考”。你实际上是在做Bar.prototype = { report: func... }; -
是的,我想是的。我对措辞有点困惑,但我想你明白了。即使它被声明为一个函数,
Foo只是一个可以调用的对象......它具有属性。默认情况下,Foo没有属性(如空对象)。然后,设置report属性。因此,如果您查看我的上一条评论(不确定您是否看到了编辑),您会看到它基本上在做什么(如最后一句话)。请记住,它不适用于您的f对象,因为您没有在Foo原型 上设置report,因此Foo实例不会“继承”它属性 -
函数 properties 不被实例继承。函数
prototype属性是。您的最后评论似乎自相矛盾,但也许我误读了。我不确定它是否会有所帮助,但请看一下 jsfiddle.net/7y9Fg 。您应该看到Fooinstances 没有report属性(因为report不在Foo.prototype中)。但是Barinstances 可以
标签: javascript prototype