下面的 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
, 运行不正常了,
觉得好意外, 这是怎么回事?
大哥你好 你的最上面的CoffeeScript是正确代码吗?我运行结果怎么是
undefined
NaN
NaN
呢
静态方法和属性,大哥你看看我用JS的方式解释你能理解不 声明变量的时候可以使用
var record=0;
但是这个变量是全局的,所以我们可以写作如下形式
var Counter={};
Counter.record=0;
也就是说将Counter作为一个命名空间,以后这个变量就叫做Counter.record了,仅仅是名字变长了。然而Counter本身还是个构造函数,可以用来创建对象,
---------------------------------------------关于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 不是在讨论js的语法本身,而是在意coffeescript为什么把@record
编译成Counter.record
而不是Counter.prototype.record
。我没学过coffeescript,但从代码的上下文也能大概猜出coffeescript如此编译的用意,不过既然已找到解决方法,就不多言了。