我有一个fiddle来帮助我理解JavaScript原型设计和继承。评论讲述了这个故事。
//From Douglas Crockford's "Javascript: the good parts": a helper to hide the "ugliness" of setting up a prototype
Function.prototype.method = function(name,func) {
this.prototype[name] = func;
return this;
}
function SomeFunc(value) {
this.setValue(value);
}
//Inherit the function (to me this conceptually the same as adding a member to a class)
SomeFunc.method('setValue', function (value) {
this.value = value;
return this;
});
try
{
SomeFunc(1);
}
catch(e)
{
alert(e);
}
为什么会出现异常?我的笔记是否正确,因为JavaScript调用继承是对于经典程序员简单地向类中添加新成员?增强和继承之间有什么区别?
答案 0 :(得分:6)
我的笔记是否正确,JavaScript调用继承是指一个经典程序员只是在一个类中添加一个新成员?
不,不是真的。在JavaScript中,我们有基于原型的继承。这意味着一个对象具有对另一个特定对象的引用,即它的原型。每当访问对象的属性时,都会搜索原型链以查找此属性。因此,如果对象本身没有此属性,则会检查其原型是否具有此属性等等。
+------------+ +-------------+
| Instance | | Prototype |
| __proto__ -+--->| __proto__ -+-->...
| foo | | bar |
+------------+ +-------------+
Instance
同时包含foo
和bar
属性。
现在,如果你有一个构造函数,你可以创建许多引用相同原型的实例(对象)。当您现在向该原型添加新属性时,所有实例也将具有此属性(由于原型链)。
这通常用于动态扩展实例,但它只是原型继承的一个结果,它本身不是继承。
增强和继承之间有什么区别?
继承是将对象的原型设置为某个对象,以便它在原型链中。增强只是复制属性。该对象将拥有该属性:
+------------+
| Instance |
| __proto__ -+--->...
| foo |
| bar |
+------------+
为什么我会收到例外?
因为您正在调用SomeFunc
像“普通”函数,而不是像构造函数一样。在这种情况下,this
会引用window
,它没有setValue
方法。
相反,您希望使用new
operator [MDN]调用它来创建新实例:
var instance = new SomeFunc(1);
如果以这种方式调用,this
将引用一个空对象,该对象继承自构造函数的prototype
属性(SomeFunc.prototype
)。
MDN has a nice article about this
and what it refers to in certain situations.
如果您查看method
正在做什么,您会看到它向SomeFunc.prototype
添加了新属性(this
引用SomeFunc
):
this.prototype[name] = func;
事实上,代码的第一部分是我上面提到的:通过扩展Function.prototype
,您可以为每个函数添加一个新属性,这样您就可以稍后调用SomeFunc.methods
。 / p>
进一步阅读:
this
答案 1 :(得分:0)
尝试改为:
new SomeFunc(1);
因为原型工作时就是这种情况