理解JavaScript中的简单类仿真器

理解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

最近,我开始学习更高级的JavaScript(因为我只在一些简单的任务中使用jQuery),并买了一本Alex MaxCaw的书《JavaScript Web应用程序》。第一章介绍如何创建简单的类仿真器。除了下面标记有注释的两行代码外,我几乎了解所有内容:

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
    被分配构造函数的内部非标准
    \u proto\u
    属性。请记住,构造函数是函数,在Javascript中,函数是对象。这意味着它们有自己的内部原型。
    prototype
    的早期引用是分配给对象crea的原型ted使用此构造函数而不是构造函数的原型本身。所有函数都继承自Function.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添加了一些非常有用的例子,非常简单。非常感谢!