2

我相信我在backbone.js 方面有很好的背景,但我有一个我不明白的问题。

假设我们有这两个视图:

BaseView = Backbone.View.extend({

    foo: {},

    initialize: function(options) {
        this.render();
    },

    render: function() {
        // ...
    }
});

PageView = BaseView.extend({

    render: function() {
        this.foo.bar = 23;
    }
});

如果我们在两个视图中检查属性 'foo',显然,它将是一个空对象:

> BaseView.prototype.foo
  Object {}
> PageView.prototype.foo
  Object {}

但是如果我们创建一个 PageView 实例,来自 BaseView 的 'foo' 属性将会改变。这怎么可能?

> page = new PageView()
> page.foo
  Object {foo: 23}
> BaseView.prototype.foo
  Object {foo: 23}

[编辑]

实际上,这是一个通用的 OOP 问题。在蟒蛇中:

class A(object):
    foo = {}

class B(A):

    def __init__(self):
        self.foo['bar'] = 23

>>> print A.foo
{}
>>> b = B()
>>> print A.foo
{'bar': 23}
4

1 回答 1

2

当你这样做时:

BaseView = Backbone.View.extend({
    foo: {},
    //...
});

foo: { }会附加到BaseView原型上。这意味着该确切对象由BaseView任何BaseView“子类”的所有实例和所有实例共享。所以鉴于此:

var BaseView = Backbone.View.extend({
    foo: {},
    //...
});
var PageView = BaseView.extend({
    //...
});
var bv = new BaseView;
var pv = new PageView;

数据看起来像这样:

bv.foo -->--+-->-- BaseView.prototype.foo -->-- { }
            |
pv.foo -->--/

所以如果你pv.foo用类似的东西改变pv.foo.x = y,你实际上是在改变BaseView.prototype.foo,这与 ; 是同一个对象bv.foo。当然,如果您pv.foo = something_else更改了引用并且bv.foopv.foo不再引用相同的底层对象。您只有一个具有多个引用的基础对象。

BaseView当您实例化或扩展or时,没有复制(既不浅也不深)PageView,您只是共享对底层对象的单个引用。

如果你希望你foo是特定于实例的(就像你几乎总是这样做的那样),那么在你的构造函数中设置它:

var BaseView = Backbone.View.extend({
    initialize: function() {
        this.foo = { };
        //...
    },
    //...
});

当然,这些initialize方法不会自行链接,因此如果需要,您必须自己执行此操作PageView

var PageView = BaseView.extend({
    initialize: function() {
        BaseView.prototype.initialize.apply(this, arguments);
        // Whatever else you need done...
    },
    //...
});

演示:http: //jsfiddle.net/ambiguous/4duQ5/


此外,您真的应该说var BaseView而不仅仅是BaseView,这并不var意味着您正在创建一个全局并且您可能不想这样做。

于 2013-05-26T20:26:43.833 回答