首页 > 解决方案 > Backbone.extend 函数究竟是如何工作的?

问题描述

我想知道这个extend函数在 Backbone.js 中是如何工作的。请在内部帮助我了解它到底在做什么。

var extend = function(protoProps, staticProps) {
    var parent = this;
    var child;

    // The constructor function for the new subclass is either defined by you
    // (the "constructor" property in your `extend` definition), or defaulted
    // by us to simply call the parent constructor.
    if (protoProps && _.has(protoProps, "constructor")) {
      child = protoProps.constructor;
    } else {
      child = function() {
        return parent.apply(this, arguments);
      };
    }

    // Add static properties to the constructor function, if supplied.
    _.extend(child, parent, staticProps);

    // Set the prototype chain to inherit from `parent`, without calling
    // `parent`'s constructor function and add the prototype properties.
    child.prototype = _.create(parent.prototype, protoProps);
    child.prototype.constructor = child;

    // Set a convenience property in case the parent's prototype is needed
    // later.
    child.__super__ = parent.prototype;

    return child;
  };

这里为什么将父级添加到子变量中?

标签: javascriptoopbackbone.js

解决方案


extend需要两个参数protoPropsstaticProps. protoProps是将分配给 Class 原型的属性,因此当您创建对象的实例时,该对象将具有该属性作为其原型链1的一部分。staticProps是对从类创建的对象不可用的道具(使用new),但可以从类本身访问,例如,通过调用CatClass.defaultMeow.

var extend = function(protoProps, staticProps) {
    var parent = this;
    var child;

在下面的讨论中parent,我们将称之为基类,我们希望将原型扩展到的类child,这里我们将其称为扩展类。

    // The constructor function for the new subclass is either defined by you
    // (the "constructor" property in your `extend` definition), or defaulted
    // by us to simply call the parent constructor.
    if (protoProps && _.has(protoProps, "constructor")) {
      child = protoProps.constructor;

ifprotoProps是一个函数,或者具有一个constructor属性(这是在您调用new类时调用(作为方法)的属性)。

    } else {
      child = function() {
        return parent.apply(this, arguments);
      };
    }

如果没有,扩展类将使用父类constructor(当您调用new它时,它将调用父类的constructor方法)。

    // Add static properties to the constructor function, if supplied.
    _.extend(child, parent, staticProps);

_.extend(target, src1,...,srcN)UnderscoreJS 方法将源对象的属性浅拷贝到目标对象。这里将所有父(静态)属性和所有传递给staticProp对象(如果提供)的属性复制到新的扩展类。

    // Set the prototype chain to inherit from `parent`, without calling
    // `parent`'s constructor function and add the prototype properties.
    child.prototype = _.create(parent.prototype, protoProps);

这可能是 Backbone.extend 例程最重要的功能:这是扩展类“继承”基类的原型链的地方。例如,如果AnimalClass.prototype.walk是原型链中的一个方法AnimalClass,将用这个新Class原型链中的方法以及所有传入的方法_.create(parent.prototype, protoProps)创建一个新Class 。这本质上是_extended原型链`,它被分配给扩展类,因为它是原型。walkprotoProps

 child.prototype.constructor = child;

这条线起初令人困惑,因为我们在上面的条件语句中看到扩展类已经被分配了一个构造函数。好吧,确实如此,但是在最后一个语句中,当我们这样做时,我们_.create(...)用基类的构造函数覆盖了扩展类的构造函数!现在我们正在重新分配它。

    // Set a convenience property in case the parent's prototype is needed
    // later.
    child.__super__ = parent.prototype;

就像评论说的那样,扩展类可以访问 ***static property* 中的基类__super__。它是从扩展类对象本身访问的便利属性。那么,在我们前面的例子中,如果 aCatClass是从 扩展而来的AnimalClass,那么以下情况为真:CatClass.__super__ === AnimalClass

    return child;
  };

推荐阅读