我有一个小提琴来帮助我理解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调用继承是对于经典程序员简单地向类中添加新成员?增强和继承有什么区别?
我的笔记是否正确,因为JavaScript调用继承是对于经典程序员简单地向类中添加新成员?
不,不是真的.在JavaScript中,我们有基于原型的继承.这意味着一个对象具有对另一个特定对象的引用,即它的原型.每当访问对象的属性时,都会搜索原型链以查找此属性.因此,如果该对象本身没有此属性,则会检查其原型以查找此属性,依此类推.
+------------+ +-------------+
| Instance | | Prototype |
| __proto__ -+--->| __proto__ -+-->...
| foo | | bar |
+------------+ +-------------+
Run Code Online (Sandbox Code Playgroud)
Instance有foo和,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以后调用.
进一步阅读: