Coffeescript 什么';这个咖啡脚本怎么了?

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

我正在迭代一些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等于第二个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这些术语有点误导。他所说的“实例变量”是指它只能在实例上访问。与任何方法一样,它只是原型的一个属性。发生的情况是,如果您使用它来存储数字/字符串/等等,那么在您为其赋值时,它将在实例中被覆盖。就你而言,没有任务