2

最近我开始学习一些更高级的 JavaScript(目前我只使用 jQuery 完成一些简单的任务)并买了一本 Alex MaxCaw “JavaScript Web Applications”的书。第一章介绍如何创建简单的类模拟器。除了下面标有注释的两行代码外,我几乎了解所有内容:

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;
};

谁能告诉我这两行的目的是什么?我会非常感激的。

4

2 回答 2

3

遍历代码:

  • 类被定义为使用提供的参数调用 init 的函数。这意味着您可以使用new例如标准构造函数语法调用它。var instance = new Thingy()并获取使用正确值init调用的函数。this
  • 如果你传入一个父类,你的类会将该类的prototype属性添加到一个新的空对象的原型链中,并将其用作 prototype属性。在现代浏览器中执行此操作的一种更简洁的方法是_class.prototype = Object.create(parent.prototype);
  • 功能已init定义。这可能会在创建实例后被更有用的初始化代码覆盖_class(或者应该更改代码以允许在init创建类时传入函数......或允许实例遍历原型链以查找其他init功能。
  • _class.fn创建它是为了提供对_class构造函数的原型函数的引用。
  • _class.fn.parent被创建以提供对构造函数的引用。如果您在其他上下文中应用原型并希望引用回原型的构造函数,这可能很有用。
  • _class._super被分配了构造函数的内部非标准__proto__属性。请记住,构造函数是函数,而在 Javascript 中,函数是对象。这意味着他们有自己的内部原型。较早的引用prototype分配给使用此构造函数创建的对象的原型,而不是构造函数的原型本身。所有函数都从 Function.prototype 继承,这是它们获取bind,apply等的地方。_super在这种情况下,它只是对 的引用Function.prototype

至于何时_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!!

哇!刚才发生了什么?事实上,你用一个对象替换了你的函数内部原型。这使您可以构建有趣的原型链并以类似的方式与函数和对象进行交互。但是请注意,与 的链接Function.prototype已被切断,这就是我们无法访问bind. 然而,让我们用更多的原型魔法来修复它!

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. 如您所见,我们的访问权限bind已经返回(当然,我们也可以使用我们最初的实现,并Function.prototype.bind.call为胜利铺平道路)。

有了这个新模式,您的代码中的功能可能会更清楚_super,即它引用了您正在制作的构造函数的内置原型_class(在我们的示例中,实例FunctionConnector将是_super)。此引用可用于在运行时修补原型,调用方法apply或其他任何您可以通过引用对象获得的东西。

正如您可能已经注意到的那样,这有点骇人听闻,尤其是因为__proto__它是非标准的。但如果你喜欢它允许的模式,它也有点整洁。如果您对 Javascript 继承的知识非常有信心,我建议您只做这样的事情,除非您负责您的整个代码库,否则甚至可能不这样做。

于 2013-09-26T21:39:22.700 回答
-1

据我所知,fn只是该prototype物业的别名

关于_super,那个是用于引用您从中继承的“类”

这里有更多关于_super和js继承的使用:文章

于 2013-09-26T20:52:54.337 回答