2

Following on from this question, I'm trying to augment Backbone.Collection with some custom methods. However, I'm getting some inconsistent behaviour between the console and the source.

Here's how the test looks

HTML

... 
<script type="text/javascript" src="./libs/underscore.js"></script>
<script type="text/javascript" src="./libs/backbone.js"></script>
<script type="text/javascript" src="./libs/backbone-extend.js"></script>    
<script type="text/javascript" src="./qunit/qunit.js"></script>
<script type="text/javascript" src="./backbone-extend-tests.js"></script>
</body></html>

backbone-extend.js

Backbone.Collection.prototype.extract = function() {
    // placeholder to test binding
    return 'foo';
};

backbone-extend-tests.js

test('extending backbone', function () {
    ok(typeof Backbone.Collection.extract == 'function');
    console.log(Backbone.Collection.extract); // undefined
});

Is there something I'm missing? I've checked that all the source is loading

JFTR - this...

_.extend(Backbone.Collection, {extract:function(){return'foo';});

...works, just not using the prototype augmenting method. I'm just unsure why one method works and the other doesn't, given that the docs for Backbone recommend prototype augmentation (although it specifically mentions Models). Guess I need to take a more detailed look under the bonnet...

UPDATE: for posterity, placing this in the backbone-extend.js file...

 _.extend(Backbone.Collection.prototype, {
     extract : function (model) {
     var _model = model;
     this.remove(model);
     return _model;
 }
 });

... works

4

2 回答 2

10

您混淆了一些关键概念,这就是为什么您没有看到您期望的行为,这是一个基本的 javascript 问题,与骨干网并不完全相关。

考虑以下构造函数:

var Klass = function() {};

您可以使用关键字调用该new构造函数以从该构造函数获取实例。

var klassInstance = new Klass();

现在,假设我想添加一个可用于从该构造函数派生的所有实例的方法。为此,我可以使用该prototype对象。

Klass.prototype.instanceMethod = function() { alert('hi'); };

然后我应该能够使用以下方法调用该方法:

klassInstance.instanceMethod();

但是,我也可以向构造函数本身添加一个静态函数——我在这个上下文中使用这个术语是松散的——可以在没有实例的情况下调用它。

Klass.staticMethod = function() { alert('yo!'); };

此方法将直接在构造函数中可用,但不能直接在实例中使用。

例如:

klassInstance.staticMethod == undefined

因此,您的测试真正有问题的是您正在prototype向该“类”的所有实例添加一个方法 - 但在您的测试中,您正在直接在“类”本身上测试一个方法。这不是一回事。


另外,尽管相关,Backbone.js 提供了一种内置机制来创建其内置类型的“子类”。这是静态 .extend()方法。这为您提供了一种将您自己的功能添加到基本 Backbone 类的简单方法。

在您的情况下,您需要执行以下操作:

var MyCollection = Backbone.Collection.extend({
    extract: function() {
        // do whatever
    }
}) 

然后,您可以创建新类的实例,这些实例将通过以下.extract()方式对它们有一个方法:

var coll = new MyCollection();
coll.extract();

TL;博士;

最终——回到你最初的问题——如果你想要一个在特定类的所有实例上都可用的方法,那么你的测试是不正确的。您要么需要新建一个实例来测试:

test('extending backbone', function () {
    var col = new Backbone.Collection();
    ok(typeof col.extract == 'function');
});

或者直接检查一个方法——这与对象不是唯一一个对象获取方法prototype的事实有细微的不同。prototype

test('extending backbone', function () {
    ok(typeof Backbone.Collection.prototype.extract == 'function');
});
于 2012-10-15T14:28:03.527 回答
0

在进行测试之前确保backbone.jsunderscore.js已满载。

于 2012-10-15T12:01:08.007 回答