CNode

CoffeeScript类的属性编译疑惑 (原来是我贴错代码了...)

Jjiyinyiyong发布于13 年前最后回复13 年前23 回复6060 浏览0 收藏

下面的 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)

J
jiangmiao#1·13 年前

@ 定义静态方法或属性

J
jiyinyiyong#2·13 年前
引用 jiangmiao@ 定义静态方法或属性

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

L
leizongmin#3·13 年前
引用 jiangmiao@ 定义静态方法或属性

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

D
douya0808#4·13 年前

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

undefined
NaN
NaN

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

 var record=0;

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

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

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

J
jiyinyiyong#5·13 年前
引用 jiangmiao@ 定义静态方法或属性

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

D
douya0808#7·13 年前
D
douya0808#9·13 年前

---------------------------------------------关于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
D
douya0808#10·13 年前
S
shiedman#11·13 年前

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

L
leizongmin#12·13 年前
J
jiyinyiyong#19·13 年前

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

参与回复
登录后即可参与回复。登录