CoffeeScript类的属性编译疑惑 (原来是我贴错代码了...)
发布于 11 年前 作者 jiyinyiyong 4836 次浏览 最后一次编辑是 8 年前

下面的 CoffeeScript 代码:

class Counter
  constructor: ([@callback](/user/callback)) ->
    console.log [@record](/user/record)
  
  [@record](/user/record): 0

  set: ->
    [@record](/user/record) += 1
    console.log [@record](/user/record)
  done: ->
    [@record](/user/record) -= 1
    console.log [@record](/user/record)
    [@callback](/user/callback)() if [@record](/user/record) is 0

demo = new Counter -> console.log "finished"
demo.set()
demo.done()

编译到 JS 是这样的:

var Counter, demo;

Counter = (function() {
  function Counter(callback) {
    this.callback = callback;
    console.log(this.record);
  }

  Counter.record = 0;

  Counter.prototype.set = function() {
    this.record += 1;
    return console.log(this.record);
  };

  Counter.prototype.done = function() {
    this.record -= 1;
    console.log(this.record);
    if (this.record === 0) {
      return this.callback();
    }
  };

  return Counter;

})();

demo = new Counter(function() {
  return console.log("finished");
});

demo.set();

demo.done();

问题在 [@record](/user/record), 本来写在 constructor 里边的话, 执行是对的 不过结果 record 不是在 Counter.prototype.record, 而是 Counter.record, 运行不正常了, 觉得好意外, 这是怎么回事?

23 回复

@ 定义静态方法或属性

没学过 Java… 这个概念不太懂… 给解释下不?

@jiyinyiyong 大概就是所有同一个类的实例共享的是同一个变量值

大哥你好 你的最上面的CoffeeScript是正确代码吗?我运行结果怎么是

undefined
NaN
NaN

静态方法和属性,大哥你看看我用JS的方式解释你能理解不 声明变量的时候可以使用

 var record=0;

但是这个变量是全局的,所以我们可以写作如下形式

var Counter={};
Counter.record=0;

也就是说将Counter作为一个命名空间,以后这个变量就叫做Counter.record了,仅仅是名字变长了。然而Counter本身还是个构造函数,可以用来创建对象,

@leizongmin 纯粹当成命名空间用的么? 觉得有点坑…

正确版本是把 @record = 0 写在 constructor 里边, 就特奇怪两个会不一样.

@jiyinyiyong 大哥你的问题是啥来着…猪弟没看懂 就是说为啥把@record写成最上面而不写在constructor中为啥不对?

@douya0808 我 91 年的… 是啊, 我就想 @record 应该也是绑在 Counter.prototype 上的嘛. 结果不是

---------------------------------------------关于this------------------------------------------------------------ 现在我们有一个构造函数F:

var F=function (){
    this.ttt=5;
}

然后我们用这个构造函数创建两个对象 var obj1=new F(); var obj2=new F(); obj1和obj2两个对象中分别有各自的实例变量ttt,值为5 所以说构造函数中this.xxx的意思就是,用这个构造函数创建对象后,每个对象中都有一个变量叫做xxx

---------------------------------------------关于静态变量----------------------------------------------------- 现在我们有一个构造函数F:(函数也是对象,我们就以对象字面量的形式来描述构造函数)

var F={
      this.name:'douya0808',//这个是实例变量,每个构造函数创建出的对象中都有各自的副本
      school='tsinghua'//这个是私有变量,想调用的话只能F.school
}

当然,JS中的对象字面量可以在最初定义完后再通过"."向里面添加属性,所以上面可以写成如下形式

var F={
      this.name:'douya0808'
}
F.school='tsinghua'

再将构造函数写成纯函数形式就是如下形式

var F=function(){
      this.name=‘douya’;
}
F.school=‘tsinghua’

你的例子中,上来创建了一个Counter对象,这个对象中有一个实例属性叫做record值为0 构造后将record直接输出,输出0 调用set,record自增1,输出1 调用done,record自减1,输出0 最后执行回调函数,输出’finished’

最后结果为

0
1
0
finished

而如果将@record写在constructor外面,就变成了Counter.record=0; 然后创建一个Counter对象,该对象里面啥属性都没有,输出undefined 在对undefined自增和自减就得到了两个NaN,最后的回调也不会执行

最后结果为

undefined
NaN
NaN

@jiyinyiyong 大哥你别闹啊 CoffeeScript的class内部 不加@才是绑定到原型上的,加了@都是绑定到构造函数名上面的

@jiyinyiyong 不是在讨论js的语法本身,而是在意coffeescript为什么把@record编译成Counter.record而不是Counter.prototype.record。我没学过coffeescript,但从代码的上下文也能大概猜出coffeescript如此编译的用意,不过既然已找到解决方法,就不多言了。

@douya0808 大哥你好厉害哦,俺学了这么久就只会写简单的几句js,感觉CoffeeScript很高深的样子。向大哥学习!

@leizongmin 同学你是在埋汰我吗

@douya0808 “埋汰”?不懂啥意思

@leizongmin 就是嘲笑的意思 东北方言

@douya0808 木有要嘲笑您的意思

@douya0808 是我贴错了, 不好意思, 之前没注意到 CoffeeScript 有这样的语法, 我的错

@leizongmin @douya0808 什么情况, 两位到底多大了… 表示 CoffeeScript 是 Node 社区另一门常用语言~

@shiedman @douya0808 我有贴错代码, 不好意思, 问题在 @ 我是拷贝的, 没有注意多出来了. 不过也有收获~

@jiyinyiyong 两位哥哥好,小弟今年才18

@leizongmin 楼上不是有哪个网站是用照片的…

@leizongmin 卖萌的人都拉稀了 拉稀了…阿兔

@douya0808 阿珠,你才拉稀呢

回到顶部