我正在迭代一些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为什么在第二个陈述中等于[]的任何想法?
答案 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]
。
你甚至可以扔一个
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
对象在你的情况下。