【问题标题】:Backbone class model not inheriting defaults骨干类模型不继承默认值
【发布时间】:2015-02-09 14:32:40
【问题描述】:

我有一个主干课程:

class BaseClass extends Backbone.Model
   defaults:
    first_name: "John"

class ExtendClass extends BaseClass
   defaults:
    last_name: "Doe"

但是,当我创建new ExtendClass 时,它没有first_name

我是否误解了 Backbone 的扩展方式?

【问题讨论】:

    标签: javascript backbone.js coffeescript


    【解决方案1】:

    我认为您误解了 CoffeeScript 的扩展方式。当你说:

    class A
        p: ...
    class B extends A
        p: ...
    

    B::p 值完全隐藏了A::p,CoffeeScript 不会尝试合并它们或链接它们或做任何特别的事情。

    Backbone 模型中的 defaults 可以是对象或函数,因此您可以使用函数和 CoffeeScript 的 super 自行合并它们:

    class BaseClass extends Backbone.Model
       defaults: ->
           first_name: "John"
    
    class ExtendClass extends BaseClass
       defaults: ->
           _(super).extend(last_name: "Doe")
    

    这将在ExtendClass 默认值中为您提供first_namelast_name

    演示:http://jsfiddle.net/ambiguous/wz6usg36/

    【讨论】:

      【解决方案2】:

      Backbone 中的extend() 助手允许您扩展原型。在没有 Backbone 的 extend 方法的纯 JavaScript 中,我们可以设置原型链,如下例所示:

      function BaseClass(opts) {
        // Here `this.defaults` will point to `BaseClass.prototype.defaults` 
        // when we create an instance of BaseClass. 
        // 
        // When we create an instance of ChildClass `this.defaults` will 
        // point to `ChildClass.prototype.defaults` if it exists, otherwise
        // it will point to `BaseClass.prototype.defaults`.
        this.attrs = _.extend({}, this.defaults, opts);
      
        // Call `BaseClass.prototype.initialize` or `ChildClass.prototype.initialize`, 
        // depending on what instance we're creating.
        this.initialize();
      }
      
      BaseClass.prototype.defaults = {
        first_name: 'anonymous',
        friend_count: 500
      };
      
      BaseClass.prototype.initialize = function() {
        console.log('Hello ' + this.attrs.first_name);
      };
      
      
      function ChildClass(opts) {
        // Let the base class set the `attrs` property 
        // and call the initialize() method.
        BaseClass.call(this, opts);
      }
      
      // Set the prototype chain
      ChildClass.prototype = Object.create(BaseClass.prototype);
      
      // Create own `defaults` object, therefore overriding
      // the one higher in the prototype chain.
      ChildClass.prototype.defaults = {
        last_name: 'backbone',
        parent_name: 'Unknown'
      };
      
      ChildClass.prototype.initialize = function() {
        // Do something...
      };
      

      从上面的例子你可以看到 ChildClass 在它的原型上设置了它自己的defaults 属性,因此当 ChildClass 实例之一查询defaults 时,JavaScript 会在 ChildClass 原型对象中找到那个并且不查找任何更远。

      这正是 Backbone 在后台发生的事情。 Backbone 将寻找一个名为defaults 的属性并将其与实例的属性合并,并且由于ChildClass 有自己的defaults 属性,Backbone 不会再查找,也不会合并BaseClass 自动为您默认。

      但是,在 Backbone 中,您可以将 defaults 属性设置为函数,然后您可以手动访问 BaseClass 的默认值,以便将它们与 ChildClass 的默认值合并。这种手动连接是有意的,因为 Backbone 不想假设您的对象层次结构(在这种情况下是您的模型)。

      在 JavaScript 中看起来像这样:

      var Note = Backbone.Model.extend({
        defaults: {
          title: 'Untitled',
          message: 'Lorem ipsum dolor...'
        },
      
        initialize: function() { /* ... */ },
      });
      
      var PrivateNote = Note.extend({
        defaults: function() {
          var defaults = _.extend({}, { date: new Date() }, Note.prototype.defaults);
      
          // You can also do this if you don't want to specify `Note` by its name:
          // var defaults = _.extend({}, { date: new Date() }, this.constructor.__super__.defaults);
      
          // `__super__` is specific to Backbone and in this case 
          // it gives you access to `Note.prototype`.
      
          return defaults;
        },
      
        initialize: function() { /* ... */ },
      });
      

      现在我们得到了我们想要的:

      var private = new PrivateNote();
      private.toJSON();
      //=> {date: Mon Feb 09 2015 00:57:14 GMT-0500 (EST), title: "Untitled", message: "Lorem ipsum dolor..."}
      

      Note 实例没有像我们预期的那样受到影响:

      var note = new Note()
      note.toJSON();
      //=> {title: "Untitled", message: "Lorem ipsum dolor..."}
      

      这是一个 js2.coffee 示例:Merge defaults with Parent defaults

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-21
        • 2016-06-05
        • 2017-11-12
        • 2013-06-30
        相关资源
        最近更新 更多