了解原型设计和扩充

P.B*_*key 0 javascript

我有一个小提琴来帮助我理解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);
}
Run Code Online (Sandbox Code Playgroud)

为什么我会得到例外?我的笔记是否正确,因为JavaScript调用继承是对于经典程序员简单地向类中添加新成员?增强和继承有什么区别?

Fel*_*ing 6

我的笔记是否正确,因为JavaScript调用继承是对于经典程序员简单地向类中添加新成员?

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

+------------+    +-------------+
|  Instance  |    |  Prototype  |
| __proto__ -+--->|  __proto__ -+-->...
| foo        |    |  bar        |
+------------+    +-------------+
Run Code Online (Sandbox Code Playgroud)

Instancefoo和,bar属性.

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

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

增强和继承有什么区别?

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

+------------+
|  Instance  | 
| __proto__ -+--->...
| foo        |    
| bar        |
+------------+
Run Code Online (Sandbox Code Playgroud)

为什么我会得到例外?

因为您调用的方式SomeFunc类似于"普通"函数,而不像构造函数.在这种情况下,this将参考window,没有setValue方法.

相反,您希望使用new运算符[MDN]调用它来创建新实例:

var instance = new SomeFunc(1);
Run Code Online (Sandbox Code Playgroud)

如果以这种方式调用,this将引用一个从构造函数的prototypeproperty(SomeFunc.prototype)继承的空对象.

MDN this在某些情况下有一篇很好的文章和它所指的内容.

如果你看看method正在做什么,你会看到它为SomeFunc.prototype(this引用SomeFunc)添加了一个新属性:

this.prototype[name] = func;
Run Code Online (Sandbox Code Playgroud)

事实上,你的代码的第一部分是我上面提到的:通过扩展Function.prototype,你为每个函数添加一个新属性,这让你SomeFunc.methods以后调用.


进一步阅读: