Coffeescript 什么';这个咖啡脚本怎么了?
我正在迭代一些api数据,并将api的数据映射到Coffeescript对象。让我困惑的是,为什么只有一部分数据会在这两个console.log语句之间消失:Coffeescript 什么';这个咖啡脚本怎么了?,coffeescript,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.item
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等于第二个console.log语句中的注释对象数组(注释是FeedItem上的属性),注释对象在那里,但没有分配-就好像注释构造函数在没有注释的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等于[]吗?我猜
API.FeedItem
构造函数中的最后一条data.comments.comments
是空的。这将导致@comments.comments
成为[]
。但你会问:
为什么最后的数据.comments.comments
值会更改项[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]
:
如果将类固定为每个实例初始化@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]
以确保数组实际上是同一个数组;额外的[1]==[1]
比较是为了向您证明=
实际上是在比较对象而不是它们的内容(即CoffeeScript的=
是JavaScript的=
)
经验法则:不要试图在类定义中定义实例变量,而是在构造函数中定义它们。我猜
API.FeedItem
构造函数中的最后一个数据.comments.comments
是空的。这将导致@comments.comments
成为[]
。但你会问:
为什么最后的数据.comments.comments
值会更改项[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]
:
如果将类固定为每个实例初始化@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]
以确保数组实际上是同一个数组;额外的[1]==[1]
比较是为了向您证明=
实际上是在比较对象而不是它们的内容(即CoffeeScript的=
是JavaScript的=
)
经验法则:不要试图在类定义中定义实例变量,而要在构造函数中定义它们。要添加到@mu中,在CoffeeScript中,这是一个太短的答案:
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;
})();
关键之处在于,在类的原型上设置
类的语句体中立即声明的项。原型在实例之间共享,这意味着在所有X
实例之间只共享一个函数对象(或一个'z'
字符串),或者在所有API.FeedItem
中只共享一个注释对象。要添加到@mu中,在CoffeeScript中,答案太短了:
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;
})();
关键之处在于,在类的原型上设置类的语句体中立即声明的项。原型在实例之间共享,这意味着在所有X
实例之间只共享一个函数对象(或一个'z'
字符串),或者在所有API.FeedItem
s之间只共享一个注释对象。回答得好,谢谢。所以,当我看一些例子,如伟大的答案,谢谢。所以当我看一些例子时,比如它声称MAX_ZOOKEEPERS是一个实例变量。这并不是一个与Ruby或Java中“instance var”一词意义相同的实例变量——它实际上只是一个静态变量,因为它在原型上声明的变量在每个实例中都是可访问的?@LoganHenriquez这些术语有点误导。他所说的“实例变量”是指它只能在实例上访问。与任何方法一样,它只是原型的一个属性。发生的情况是,如果您使用它来存储数字/字符串/等等,那么在您为其赋值时,它将在实例中被覆盖。就你而言,没有任务