扩展Backbone.Collection原型

sun*_*ung 2 javascript qunit backbone.js

这个问题之后,我试图用一些自定义方法来扩充Backbone.Collection.但是,我在控制台和源之间出现了一些不一致的行为.

这是测试的样子

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>
Run Code Online (Sandbox Code Playgroud)

骨干-extend.js

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

骨干-扩大,tests.js

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

有什么我想念的吗?我检查过所有的源都在加载

JFTR - 这......

_.extend(Backbone.Collection, {extract:function(){return'foo';});
Run Code Online (Sandbox Code Playgroud)

......工作,只是不使用原型扩充方法.我只是不确定为什么一种方法有效而另一种方法无效,因为Backbone的文档建议使用原型扩充(尽管它特别提到了模型).猜猜我需要在引擎盖下更详细一点......

更新: 为后代,将其放在backbone-extend.js文件中......

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

......有效

J. *_*mes 10

您正在混淆一些关键概念,这就是为什么您没有看到您期望的行为,这更像是一个基本的JavaScript问题,而不是完全与骨干相关.

考虑以下构造函数:

var Klass = function() {};
Run Code Online (Sandbox Code Playgroud)

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

var klassInstance = new Klass();
Run Code Online (Sandbox Code Playgroud)

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

Klass.prototype.instanceMethod = function() { alert('hi'); };
Run Code Online (Sandbox Code Playgroud)

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

klassInstance.instanceMethod();
Run Code Online (Sandbox Code Playgroud)

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

Klass.staticMethod = function() { alert('yo!'); };
Run Code Online (Sandbox Code Playgroud)

此方法将直接在构造函数之外提供,但不会直接从实例中获得.

例如:

klassInstance.staticMethod == undefined
Run Code Online (Sandbox Code Playgroud)

所以你的测试真正的错误在于你正在为一个方法添加一个方法prototype- 该方法可用于该"类"的所有实例 - 但是在你的测试中,你正在直接在"类"本身上测试一个方法.这不是一回事.


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

在你的情况下,你会想做类似的事情:

var MyCollection = Backbone.Collection.extend({
    extract: function() {
        // do whatever
    }
}) 
Run Code Online (Sandbox Code Playgroud)

然后,您可以创建新类的实例,这些实例将通过以下.extract()方式对其进行处理:

var coll = new MyCollection();
coll.extract();
Run Code Online (Sandbox Code Playgroud)

TL; DR;

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

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

或者prototype直接检查一个方法 - 这是因为prototype对象不是获取方法的对象的唯一事实.

test('extending backbone', function () {
    ok(typeof Backbone.Collection.prototype.extract == 'function');
});
Run Code Online (Sandbox Code Playgroud)