Inheritance Coffeescript:声明类的成员变量危险吗?

Inheritance Coffeescript:声明类的成员变量危险吗?,inheritance,coffeescript,Inheritance,Coffeescript,拥有一个coffeescript类,如: class A headers: [] addHeader: (name, value) -> @headers.push { name: name, value: value } a = new A() a.addHeader 'header1', 'value1' console.log 'A:', a.headers console.log '---' b = new A() b.addH

拥有一个coffeescript类,如:

class A
  headers: []

  addHeader: (name, value) ->
    @headers.push {
      name: name,
      value: value
    }


a = new A()
a.addHeader 'header1', 'value1'
console.log 'A:', a.headers
console.log '---'
b = new A()
b.addHeader 'header2', 'value2'
console.log 'B:', b.headers
console.log '---'
console.log 'A:', a.headers
执行此脚本将提供以下输出:

A: [ { name: 'header1', value: 'value1' } ]
---
B: [ { name: 'header1', value: 'value1' },
  { name: 'header2', value: 'value2' } ]
---
A: [ { name: 'header1', value: 'value1' },
  { name: 'header2', value: 'value2' } ]
为什么元组
{'header2':'value2'}
也被添加到第一个对象
A

这是一把小提琴:


我一定做错了。尽管我更喜欢为类声明成员变量,以便跟踪它们。

这是因为您的类将编译为:

var-A;
A=(函数(){
函数A(){}
A.prototype.headers=[];
A.prototype.addHeader=函数(名称、值){
返回此.headers.push({
姓名:姓名,,
价值:价值
});
};
返回A;
})();
如您所见,
标题
是原型的属性。由于您没有为您创建的
A类的每个实例重写它(
A
b
),因此当
this.headers.push在
addHeader
方法中调用时,它总是修改相同的数组-属于
A.prototype
的数组

要为类的每个实例创建唯一的
数组,请使用
构造函数
函数。试着这样做:

A类
构造函数:->
@标题=[]
addHeader:(名称、值)->
@1.push{
姓名:姓名,,
价值:价值
}

您可以在中了解更多信息。

这不是真正的CoffeeScript问题,顺便说一句,这是JavaScript中原型工作方式的副作用。不要将可变属性附加到原型,因为原型属于所有人。OTOH,如果您明确希望共享可变属性,请将其附加到原型上,然后您需要一条注释来解释其用途,否则人们可能会认为这是一个bug。谢谢。因此,我应该始终在构造函数中分配成员变量?或者什么是“最佳实践”?答案当然是“视情况而定”。不可变的东西(字符串、数字、布尔值)在原型中很好,因为不指定新值就无法更改它们,也不会干扰原型。在内部化原型系统的工作方式之前,使用构造函数可能更安全、更一致。