了解原型设计和扩充

时间:2011-10-18 18:44:11

标签: javascript

我有一个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调用继承是对于经典程序员简单地向类中添加新成员?增强和继承之间有什么区别?

2 个答案:

答案 0 :(得分:6)

  

我的笔记是否正确,JavaScript调用继承是指一个经典程序员只是在一个类中添加一个新成员?

不,不是真的。在JavaScript中,我们有基于原型的继承。这意味着一个对象具有对另一个特定对象的引用,即它的原型。每当访问对象的属性时,都会搜索原型链以查找此属性。因此,如果对象本身没有此属性,则会检查其原型是否具有此属性等等。

+------------+    +-------------+
|  Instance  |    |  Prototype  |
| __proto__ -+--->|  __proto__ -+-->...
| foo        |    |  bar        |
+------------+    +-------------+

Instance同时包含foobar属性。

现在,如果你有一个构造函数,你可以创建许多引用相同原型的实例(对象)。当您现在向该原型添加新属性时,所有实例也将具有此属性(由于原型链)。

这通常用于动态扩展实例,但它只是原型继承的一个结果,它本身不是继承。

  

增强和继承之间有什么区别?

继承是将对象的原型设置为某个对象,以便它在原型链中。增强只是复制属性。该对象将拥有该属性:

+------------+
|  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>


进一步阅读:

答案 1 :(得分:0)

尝试改为:

new SomeFunc(1);

因为原型工作时就是这种情况