Backbone.extend 函数究竟是如何工作的?

How exactly does the Backbone.extend function work?

我想知道这个 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;
  };

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

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

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

在下面的讨论中 parent 是我们将要调用的 Base Class,class 我们要扩展到 child 的原型,在这里我们将调用扩展 Class。

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

如果 protoProps 是一个函数,或者有一个 constructor 属性(这是当您调用 new 在 Class 上)。

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

如果不是,Extended Class 将使用父级的 constructor(当您调用 new 时,它将调用父级的 constructor 方法)。

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

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

    // 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 例程最重要的功能:这是扩展 Class "inherits" 基础 Class' 原型链的地方。例如,如果 AnimalClass.prototype.walkAnimalClass 原型链中的一个方法,_.create(parent.prototype, protoProps) 将使用此新 walk 方法创建一个新的 Class =64=] 原型链,以及传入的所有 protoProps。这本质上是 _extended 原型链`,它被分配给 Extended Class,因为它是原型。

 child.prototype.constructor = child;

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

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

正如评论所说,Extended Class 可以访问 ***static 属性* __super__ 中的 Base Class。这是从扩展 Class 对象本身访问的便利 属性。那么,在我们前面的例子中,如果 aCatClass 是从 AnimalClass 扩展而来的,那么以下内容为真:CatClass.__super__ === AnimalClass

    return child;
  };