CoffeeScript私有类实例变量

时间:2012-03-27 09:29:55

标签: javascript coffeescript

我有以下CoffeeScript代码:

class Person
  secret = 0
  constructor: (@name, @age, @alive) ->
  inc: -> secret++

编译为以下JavaScript代码:

var Person;
Person = (function() {   
    var secret;
    secret = 0;

    function Person(name, age, alive) {
        this.name = name;
        this.age = age;
        this.alive = alive;
    }
    Person.prototype.inc = function() {
        return secret++;
    };
    return Person;
})();

secret的所有实例之间共享Person。有没有办法在CoffeeScript中使secret成为私有实例变量?

9 个答案:

答案 0 :(得分:18)

我找到了解决方案。我不确定这是否是最好的解决方案,所以我仍然对其他人开放。

CoffeeScript的:

class Person
  constructor: (@name, @age, @alive) ->
    secret = 0
    @inc = -> secret++;

JavaScript的:

var Person;
Person = (function() {
    function Person(name, age, alive) {
        var secret;
        this.name = name;
        this.age = age;
        this.alive = alive;
        secret = 0;
        this.inc = function() {
            return secret++;
        };
    }
    return Person;
})();

答案 1 :(得分:17)

CoffeeScript中没有私有成员的概念,因为JavaScript中没有。有一些局部变量,你可以很好地利用in your own solution,但是当你的解决方案确实隐藏secret函数之外的任何变量时,它也会引入重新声明{{}}的开销。类constructor的每个实例化上的{1}}方法。

JavaScript社区中一个非常常见的错误是尝试在其上预测其他语言的不存在的功能,这种模仿私人成员的尝试显然是一个例子。在其中没有这样的概念,并且深入思考,你会得出结论,JavaScript是一个非常宽松的动态环境,这将是不自然的。

因此,不要浪费你的时间和你的应用程序的性能来实现不存在的结构。只需专注于解决您的问题 - 而不是缺乏语言功能的问题。

现在问问自己:让所有成员公开会有什么伤害?

考虑到所有因素,最终解决方案将是:

inc

答案 2 :(得分:2)

虽然它不会真正隐藏它们,但惯例是在“私人”成员前加上下划线。这里的想法是,使用它的人应该假设这些成员是实现细节,并建议不要使用它们。

答案 3 :(得分:1)

参考this thread,你只能通过封闭的getter函数使其工作

答案 4 :(得分:1)

这是一个大多数时间都能满足要求的技巧:

msg = "Result-----------\n"

class Dog

  #public variable
  dogName: null

  #private variables
  _private = []

  constructor: (@dogName, surname) ->
    _private[@dogName] = {surname: surname}

  #public method (note the => instead of ->)
  walk: =>
    msg += "#{@dogName} is walking\n"
    sayHello(@dogName, _private[@dogName].surname)

  #private method
  sayHello = (dog, surname) ->
    msg += "Hi! says #{dog}. Call me #{surname}\n"

window.ralph = new Dog("Ralph", "Ralphie")
window.peter = new Dog("Peter", "Pitty")
window.rex = new Dog("Rex", "Roxie")
rex.walk()
peter.walk()
ralph.walk()

alert msg

但是你必须记住:_private随着每个新实例(它是一个共享数组)而增长,你的密钥(在这种情况下是@dogName)必须在整个实例中是唯一的。

Try it

答案 5 :(得分:0)

您实际上是通过声明成员私有来隐藏实现细节。通过使用继承,您可以通过声明一个“抽象”类(实际上在CoffeeScript中不存在,据我所知)并使用您自己的实现扩展它来隐藏实现细节。像这样:

  class bottle
        drink: ->
        empty: ->

  class bottle_impl extends bottle
        drink: -> 
             if count > 0
                 alert "drinking for the " + _count + " time."
       empty: -> @_count = 0
       _count: 4

现在每个返回瓶子的函数实际上应该返回一个bottle_impl(同时在注释中将该事实隐藏起来)。不幸的是,当延长一个瓶子时,你不会扩展一个可能不是你想要的bottle_impl。

答案 6 :(得分:0)

嗯,不完全正确。如果你想要私人会员,你可以真正得到私人会员,但如果你真的想要它,你可以拥有它

class person 
  constructor:->
    name='my secret name'
    @getName=->
      name
    null


boy= new person()


alert boy.name  #it's now private spits out undefined
alert boy.getName()

他们需要在构造的范围内才能使其工作。 它就像你将要获得的那样接近私密。

私人问题的问题会降低应用程序的速度。 它需要每次运行时运行,它不能从原型中获取它。 玩得开心

答案 7 :(得分:0)

你可以这样做......

class person
  secret = 
    name : "my secret name"
  constructor:->
    x = 123
  getName: ->
    secret.name

user = new person()

console.log user.name # undefined
console.log user.getName() # "my secret name"

它非常私密,缺点是您必须使用变量secret_或您选择引用私有变量的任何内容。

答案 8 :(得分:0)

虽然Javascript没有可见性概念,但您可以使用范围来模拟它。

class Test
  privateVariable = null

  privateFunction = (obj)->
    privateVariable = obj
  constructor: (a) ->
    privateVariable = a

  publicFunction: ->
    return privateVariable

  setPrivateVariable: (obj) ->
    privateFunction(obj)

test = new Test("Test")
console.log(test.privateVariable)   # undefined
console.log(test.publicFunction())  # Test
test.setPrivateVariable("Changed!") #
console.log(test.publicFunction())  # Changed!

这是一个非常值得商榷的主题。我个人喜欢隐藏一些属性和方法,以使类合同更清晰。