【问题标题】:Why instanceof keyword does not work with Backbone js models?为什么 instanceof 关键字不适用于 Backbone js 模型?
【发布时间】:2013-08-21 09:25:04
【问题描述】:

我正在构建一个涉及继承和使用 instanceof javascript 关键字的 Backbone JS 应用程序。

我有以下代码:

app.Sport = Backbone.Model.extend
({
    defaults:
    {
        id: 0,
        title: 'Running'
    }
});

在代码中,我通过键入以下内容来实例化一个新的运动:

var newSport = new app.Sport ();

我可以毫无问题地操作这个新创建的实例。

但是,因为有一个but,所以instanceof关键字在询问我的实例类型时总是返回false:

console.log ('is newSport a Sport instance ? ' + newSport instanceof app.Sport);

总是显示为假。为什么?

注意:我没有在我的问题中提到继承,因为它甚至不适用于 OOP 的简单形式(基类的一个实例,并要求紧随其后的类型)。

我最初的目的是根据运动的类型触发特定的动作(因此使用 instanceof 关键字);它可能是一个很酷的,也可能是一个极端的:

app.CoolSport = app.Sport.extend ({ ... });
app.ExtremeSport = app.Sport.extend ({ ... });

编辑:我隔离了这个问题。它没有链接到 instanceof 关键字或我声明的模型。相反,我填充了一个 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 集合的初始化是问题所在。

有什么想法吗?

【问题讨论】:

  • 我很想重现您的问题,但我的测试表明这应该可以按预期工作。您使用的是哪个版本的主干/下划线? (小提琴:jsfiddle.net/HHS8u
  • 试着写下console.log ('is newSport a Sport instance ', (newSport instanceof app.Sport)); - 你得到 instanceof 'is newSport a Sport instance ? + newSport - 这将是一个字符串
  • 对我来说也一样:它正在使用 jsfiddle。不是版本问题。请查看我更新的问题(问题与收藏有关)。

标签: javascript oop backbone.js


【解决方案1】:

请不要这样:

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);

【讨论】:

  • 我永远不会做坏事。感谢您指出我这个错误。请查看我更新的问题,因为它说明了我遇到的真正问题。
【解决方案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实例,从而保留了它的子类型。

感谢大家的帮助,希望我的回答能帮助到其他人:-)

【讨论】:

    【解决方案3】:

    您将集合中的模型定义为“app.Sport”

    所以当你推送coolSport1.toJSON()时,会使用app.Sport模型初始化

    这就是为什么它不是 CoolSport 实例而是 Sport 实例的原因。

    【讨论】:

    • 我在你之前几分钟就发现了同样的问题(见我的回答就在下面),确实是正确的解决方案。如果我没有自己找到它,很高兴你在那里;-)
    猜你喜欢
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-06
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    相关资源
    最近更新 更多