我正在构建一个涉及继承和使用instanceof javascript关键字的Backbone JS应用程序。
我有以下代码:
app.Sport = Backbone.Model.extend
({
defaults:
{
id: 0,
title: 'Running'
}
});
此外,在代码中,我通过输入:
来实例化一个新的Sportvar newSport = new app.Sport ();
我可以毫无问题地操纵这个新创建的实例。
但是,因为有一个但是,当询问我的实例类型时,instanceof关键字总是返回false:
console.log ('is newSport a Sport instance ? ' + newSport instanceof app.Sport);
始终显示false。为什么?
注意:我没有在我的问题中提到继承,因为它甚至不能使用简单形式的OOP(基类的一个实例,并在之后询问类型)。
我最初的目的是根据运动的类型触发特定的动作(因此使用instanceof关键字);它可能是一个很酷的,或者是一个极端的:
app.CoolSport = app.Sport.extend ({ ... });
app.ExtremeSport = app.Sport.extend ({ ... });
编辑:我隔离了这个问题。它没有链接到instanceof关键字或我声明的Model。相反,我填充了Backbone集合,并推动了一些不同类型的运动。这是测试代码:(Fiddle)
var app = {};
app.Sport = Backbone.Model.extend
({
defaults:
{
id: 0,
title: 'Running'
}
});
app.CoolSport = app.Sport.extend
({
defaults:
{
uselessAttr:'I am a Cool Sport !'
}
});
app.SportList = Backbone.Collection.extend
({
model: app.Sport
});
var coolSport1 = new app.CoolSport();
console.log ('is coolSport1 a Sport instance ? ' , coolSport1 instanceof app.Sport);
console.log ('is coolSport1 a CoolSport instance ? ' , coolSport1 instanceof app.CoolSport);
console.log ('is coolSport1 a CoolSport instance (wrong operand in console) ? ' + coolSport1 instanceof app.CoolSport);
var sportList = new app.SportList();
sportList.push (coolSport1.toJSON());
sportList.each ( function ( sport )
{
if ( sport instanceof app.CoolSport )
{
console.log ( "sport is an instance of Cool Sport ! Yeah !" , sport instanceof app.CoolSport ) ;
}
else
{
console.log ( "Not a CoolSport instance..");
}
});
猜猜是什么?我的CoolSport实例......不是CoolSport实例。我怀疑Backbone SportList集合的初始化是个问题。
有什么想法吗?
答案 0 :(得分:5)
请不要这样:
console.log ('is newSport a Sport instance ? ' + newSport instanceof app.Sport);
做得对:
console.log ('is newSport a Sport instance ? ' + (newSport instanceof app.Sport));
或
console.log ('is newSport a Sport instance ? ', newSport instanceof app.Sport);
答案 1 :(得分:2)
我找到了解决方案: - )
我评论了下面的代码:
var coolSport1 = new app.CoolSport();
// Of course it is
console.log ('is coolSport1 a Sport instance ? ' , coolSport1 instanceof app.Sport);
console.log ('is coolSport1 a CoolSport instance ? ' , coolSport1 instanceof app.CoolSport);
var sportList = new app.SportList();
// Here is the tricky part : we push the JSON representation of our CoolSport instance
sportList.push (coolSport1.toJSON());
// Backbone does not know anymore the subtype of our instance, as it has been JSON stringified juste before.
sportList.each ( function ( sport )
{
if ( sport instanceof app.CoolSport )
{
console.log ( "sport is an instance of Cool Sport ! Yeah !" , sport instanceof app.CoolSport ) ;
}
else
{
console.log ( "Not a CoolSport instance..");
}
});
Backbone文档提供了这种行为的机制:
var Library = Backbone.Collection.extend({
model: function(attrs, options) {
if (condition) {
return new PublicDocument(attrs, options);
} else {
return new PrivateDocument(attrs, options);
}
}
});
它告诉集合如何处理JSON表示,以便向列表中添加正确的子类型实例。因此,要在保持代码不变的情况下添加CoolSport,只需要在SportList集合中添加模型函数,如果它包含'uselessAttr',则返回一个新的CoolSport(参见我的问题中的代码)。
我采用了不同的方式,直接通过集合的add()方法传递一个CoolSport实例,从而保留了它的子类型。
感谢大家的帮助,并希望我的回答能够帮助其他人: - )
答案 2 :(得分:1)
您正在将集合中的模型定义为“app.Sport”
所以当你推送coolSport1.toJSON()时,它将使用app.Sport模型进行初始化
这就是为什么它不是CoolSport实例而是Sport实例。