理解JavaScript中的简单类仿真器
最近,我开始学习更高级的JavaScript(因为我只在一些简单的任务中使用jQuery),并买了一本Alex MaxCaw的书《JavaScript Web应用程序》。第一章介绍如何创建简单的类仿真器。除了下面标记有注释的两行代码外,我几乎了解所有内容:理解JavaScript中的简单类仿真器,javascript,prototypal-inheritance,Javascript,Prototypal Inheritance,最近,我开始学习更高级的JavaScript(因为我只在一些简单的任务中使用jQuery),并买了一本Alex MaxCaw的书《JavaScript Web应用程序》。第一章介绍如何创建简单的类仿真器。除了下面标记有注释的两行代码外,我几乎了解所有内容: var Class = function(parent) { var _class = function() { this.init.apply(this, arguments); }; if(pa
var Class = function(parent) {
var _class = function() {
this.init.apply(this, arguments);
};
if(parent) {
var subclass = function() {};
subclass.prototype = parent.prototype;
_class.prototype = new subclass();
};
_class.prototype.init = function() {};
_class.fn = _class.prototype;
//????
_class.fn.parent = _class;
//????
_class._super = _class.__proto__;
return _class;
};
有谁能告诉我这两行的目的是什么?非常感谢。据我所知,
fn
只是原型
属性的别名
关于\u super
,它是用来引用您从中继承的“类”
以下是有关使用
\u super
和js继承的更多信息:浏览代码:
- 类定义为一个函数,该函数使用提供的参数调用init。这意味着您可以使用标准构造函数语法使用
调用它,例如new
并使用适当的var instance=new Thingy()
值调用This
函数init
- 如果传入父类,则类会将该类的
属性添加到新空对象的原型链中,并将其用作其prototype
属性。在现代浏览器中,更简洁的方法是prototype
\u class.prototype=Object.create(parent.prototype)代码>
- 定义了
函数。在创建init
实例后,这可能会被更有用的初始化代码覆盖(或者应该更改代码,以便在创建类时允许传入\u class
函数……或者允许实例遍历原型链以查找其他init
函数)init
- 创建
是为了提供对\u class.fn
构造函数原型函数的引用\u class
的创建是为了提供对构造函数的引用。如果您在其他上下文中应用原型,并且希望引用原型的构造函数,这可能会很有用\u class.fn.parent
被分配构造函数的内部非标准\u class.\u super
属性。请记住,构造函数是函数,在Javascript中,函数是对象。这意味着它们有自己的内部原型。\u proto\u
的早期引用是分配给对象crea的原型ted使用此构造函数而不是构造函数的原型本身。所有函数都继承自Function.prototype,这是它们获得prototype
,绑定
,等等的地方。在本例中,应用
只是对\u super
的引用函数.prototype
\u super
,可以想象如下操作:
function Maker(){ //this will be called as a constructor, ie. with new
var fun = function(){}; //Make a function
fun.__proto__ = this.__proto__; //yuck. Set the function's this value to the instance
return fun; //return the function
}
Maker.prototype={say:function(){console.log("Javascript is fun!.. And weird.")}};
var fun = new Maker();
fun.say() //"Javascript is fun!.. And weird."
console.log(fun.__proto__) // Object{say:function}
console.log(fun.bind) // undefined!!
哇!刚才发生了什么事?
事实上,您将函数内部原型替换为对象。这允许您建立有趣的原型链,并以类似的方式与函数和对象进行交互。但是,请注意,与函数.prototype
的链接已断开,这就是为什么我们无法访问绑定
。不过,让我们修复一下它与更多的原型魔术
function FunctionConnector(obj){
for (var prop in obj){
if(obj.hasOwnProperty(prop){
this.prop=obj.prop
}
}
}
FunctionConnector.prototype=Function.prototype;
Maker.prototype=new FunctionConnector({say:function(){
console.log("Javascript is fun!.. And weird.")
}});
var fun = new Maker();
fun.say() //"Javascript is fun!.. And weird."
console.log(fun.__proto__) // Object{say:function}
console.log(fun.bind) // function bind(){ [native code] }
现在,什么是FunctionConnector
?它接受一个对象,当作为构造函数调用时,返回一个对象,该对象既具有传递对象的所有属性,又继承自Function.prototype
。正如您所见,我们对绑定的访问已返回(当然,我们也可以使用最初的实现,只需Function.prototype.bind.call
就可以获得胜利)
有了这个新模式,您的代码中的\u super
的功能可能会更加清晰,即它引用了您正在创建的\u类
构造函数的内置原型(在我们的示例中,FunctionConnector
的实例将是\u super
)。此引用可用于在运行时修补原型,使用apply
调用方法,或通过引用对象调用任何其他方法
这是,正如您可能已经注意到的,有点黑客行为,特别是因为\uuuuu proto\uuuuu
是非标准的。但是如果您喜欢它允许的模式,它也有点整洁。我建议您只在对Javascript继承的知识非常自信的情况下才这样做,即使是这样,除非您负责您的继承整个代码库。\u super是John Resig在其扩展模型中定义的一个属性,因此我们可以在子类中调用父函数。@grape\u mao好的,但我不理解我在上面发布的这段简单代码中的目的。@grape\u mao这是不幸的我的问题。上面的代码就是我所有的代码。这本书没有提供f使用此_super。但感谢您的关注和提供的链接。@voronwe3您感谢了错误的人…实际上是我否决了此答案,因为那篇文章中的_super可能有不同的用途。JavaScript继承没有父属性
和父属性
属性。这只是“伪造”它们,所以你可以使用它们。_class.fn.parent现在对我来说更清楚了。但我仍然对_super有点困惑。我无法想象我可以使用_super的情况。你能告诉我更多一点吗?也许是一些例子吗?@voronwe3添加了一些非常有用的例子,非常简单。非常感谢!