这个Coffeescript有什么问题?

时间:2012-05-15 02:13:49

标签: coffeescript

我正在迭代一些api数据并将API的数据映射到Coffeescript对象。令我困惑的是为什么只有部分数据在这两个console.log语句之间消失:

items = (for item in @apiFeedPage.items
         fi = new API.FeedItem(item, @apiFeedPage.instance_url)
         console.log fi.comments.comments
         window.API.itemHash[fi.id] = fi  #save for later usage
         fi )       
console.log items[0].comments.comments

在上面,第一个console.log输出我期望的注释:fi.comments.comments等于Comment对象数组(Comments是FeedItem上的属性)在第二个console.log语句中,注释对象在那里但没有分配 - 好像Comment构造函数是在没有注释的API响应上运行的。

构造函数如下所示:

class API.FeedItem extends API.FeedComponent 
  # instance vars
  comments: {}

  constructor: (data, instance_url) ->
    super(data, instance_url)
    @parent = new API.User( data.parent )
    @comments.comments = (new API.Comment(api_comment) for api_comment in data.comments.comments)   
    @comments.total = data.comments.total
    @comments.nextPageUrl = data.comments.nextPageUrl

我已经确认在构造函数中,@ comments.comments已正确分配,这是您所期望的,因为第一个console.log语句具有预期的对象。上面的第一个代码块使用胖箭头位于Ajax回调函数中,因此我最初怀疑这与丢失“this”的上下文有关,似乎不适用,并且因为FeedItem中的所有其他预期数据在那里......

关于第[0]项.comments.comments为什么在第二个陈述中等于[]的任何想法?

2 个答案:

答案 0 :(得分:3)

我猜你的data.comments.comments构造函数中的最后一个API.FeedItem是空的。这会导致@comments.comments成为[]。但是你会问:

  

为什么最后data.comments.comments值会更改items[0]

答案很简单,这个:

class API.FeedItem extends API.FeedComponent 
  # instance vars
  comments: {}

创建一个comments = { }对象,该对象附加到API.FeedItem原型,因此由API.FeedItem的所有实例共享;换句话说,评论是谎言,这不是实例变量。

根据您的情况考虑这种简化的模拟:

class AFI
  comments: { }
  constructor: (n) ->
    @comments.comments = [ 1 .. n ]

fitems = [ 1 .. 4 ]
items = (new AFI(i) for i in fitems)
console.log item.comments for item in items

您可能希望看到[1][1,2][1,2,3][1,2,3,4]出来,但您会看到四个相同的[1,2,3,4]http://jsfiddle.net/ambiguous/hf9zL/

如果你修改了你的类来初始化每个实例@comments

class AFI
  constructor: (n) ->
    @comments = { }
    @comments.comments = [ 1 .. n ]

然后,您会看到您期待的[1][1,2][1,2,3][1,2,3,4]

  

演示:http://jsfiddle.net/ambiguous/qs9Zy/

你甚至可以扔一个

console.log items[0].comments.comments == items[1].comments.comments
console.log [1] == [1]

in看到数组实际上是同一个数组;额外的[1] == [1]比较是为了向您证明==实际上是在比较对象而不是其内容(即CoffeeScript的==是JavaScript的===)。

经验法则:不要尝试在类定义中定义实例变量,在构造函数中定义它们。

答案 1 :(得分:1)

在CoffeeScript中添加到@mu的答案太短了

class X
  y: -> console.log 'y!'
  z: 'z'

被翻译为:

var X;

X = (function() {

  function X() {}

  X.prototype.y = function() {
    return console.log('y!');
  };

  X.prototype.z = 'z';

  return X;

})();

关键点是,在class语句正文中声明的项目是在类原型上设置的。在实例之间共享原型,这意味着在所有'z'个实例中共享一个函数对象(或一个X字符串),或者在所有{{1}中共享一个comments对象在你的情况下。