2012-03-07 64 views
2

我一直在玩Backbone.js,遇到了一些意外。看起来,如果我明确地设置属性,那么toJSON()(以及作为属性的结果)将只返回一个JSON对象。这里的问题:model.toJSON()返回空对象

  1. 扩展/继承一个样本对象的一些数据
  2. 抢得到的构造
  3. 实例化/新实例
  4. 调用toJSON()功能

我预期调用返回我的对象​​的所有属性(继承和绑定),但我回来了一个空的{}对象。

这里的示例代码:

var TestModelConstructor = Backbone.Model.extend({ name: "test", num: 483 }); 
var testinstance = new TestModelConstructor; 

console.log(testinstance.name); //prints: test 
console.log(testinstance.num); //prints: 483 
console.log(JSON.stringify(testinstance.toJSON())); //prints: {} 
console.log(testinstance.attributes); //again empty object 

testinstance.newattr = "adding new attribute"; 
console.log(testinstance.attributes); //{} ???? 

//either set explicitly by calling "set" or via constructor/initialize 
testinstance.set({ label: "i can setz attributez" }); 
console.log(JSON.stringify(testinstance.toJSON())); 
             //{"label":"i can setz attributez"} 
console.log(testinstance.attributes); //{"label":"i can setz attributez"} 

无论这种行为是奇怪的或我错过了文档中的东西。

回答

3

我认为你应该使用defaults参数来extend功能设置的默认值。传递给扩展函数的参数将是类中的成员而不是属性,这是toJSON使用的参数。

var TestModelConstructor = Backbone.Model.extend({ 
    defaults : { name: "test", num: 483 } 
}); 
var testinstance = new TestModelConstructor; 
.... 

查看defaults documentation了解更多详情。

要清楚的是,属性Backbone.Model使用存储在该类的attributes成员而不是实际的类本身。这可以避免将实际模型数据与您在模型上调用的功能以及用于配置模型的设置混淆。当您将参数传递给Model.extend函数时,您正在创建/设置的是这些函数和设置。

所以,当你试图设置testinstance.newattr你应该实际使用testinstance.attributes.newattr代替。这就是.set方法实际上是在做幕后,所以我只是用.set建议。

同样,attributes documentation有更多的细节

+0

谢谢。再次查看属性部分的确能够澄清这个问题,我希望文档在这个MVC框架中使用的约定更加清晰,当我第一次阅读它的时候,我已经把它作为推荐而不是公约。 – 2012-03-07 17:25:49

+0

没问题。实际上我后来碰到了一些类似的困惑 - 我发现你需要的大部分信息都在文档中,只是需要一些正确的阅读才能把它弄清楚。无论如何,如果您认为这是正确的答案,请将其标记为正确。 – obmarg 2012-03-07 17:40:24

1

其实你混起来

,你做的事:

var TestModelConstructor = Backbone.Model.extend({ name: "test", num: 483 }); 

你应该做的:

var TestModelConstructor = Backbone.Model.extend({}); 

此言请记住th E具有不需要是空的,但只是用于测试,没有任何自定义的方法延伸的新模式是不够的。

那么,当你这样做:

var testinstance = new TestModelConstructor; 

你应该做的:

var testinstance = new TestModelConstructor({ name: "test", num: 483 }); 

此言在这里,您将创建一个定义模型的新对象,你给你的modelObject一些值,名称和数量。

这些属性仅在实例中可用,但它们是实例的属性。 如果您希望将这些属性作为每个实例的默认值,那么当您从Backbone.Model扩展时,应将其设置在模型定义中。是这样的:

var TestModelConstructor = Backbone.Model.extend({ 
    defaults: { 
     name: 'defaultname', 
     num: 0 
    } 
}); 

此言每个实例现在可以创建将得到'defaultname'的name属性(除非你用name属性给定的值创建实例

来概括:

var TestModelConstructor = Backbone.Model.extend({ 
    defaults: { 
     name: 'defaultname', 
     num: 0 
    } 
}); 

// create a test instance 
var testinstance = new TestModelConstructor(); 

console.log(testinstance.get('name')); // output: defaultname 

// create a testinstance and override the defaults (you can override them partially) 
var testinstance2 = new TestModelConstructor({ name: "test", num: 483 }); 

console.log(testinstance.get('name')); // output: test 
+0

谢谢你添加这个优秀的评论。我完全错过了使用默认值与显式设置实例值的构造函数的原型继承方面。当我尝试使用我的初始版本(在问题中)时,我看到了模型原型上的属性,而不是模型本身的属性,但当时我没有太在意。但这当然有助于把事情放在眼里。 – 2012-03-11 19:10:02