CoffeeScript私有类实例变量
CoffeeScript Private Class Instance Variables
我有以下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;
})();
当前CCD_ 1在CCD_ 2的所有实例之间共享。有没有办法让secret
成为CoffeeScript中的私有实例变量?
我找到了一个解决方案。我不确定这是否是最好的解决方案,所以我仍然对其他人持开放态度。
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;
})();
CoffeeScript中没有私有成员的概念,因为JavaScript中没有。有一些局部变量,您可以在自己的解决方案中很好地利用这些变量,但尽管您的解决方案确实对constructor
函数之外的任何东西隐藏了secret
变量,但它也引入了在类Person
的每次实例化中重新声明inc
方法的开销。
在JavaScript社区中,一个非常常见的错误是试图在其上投影其他语言不存在的功能,模仿私人成员的尝试显然就是一个例子。这里面没有这样的概念,深入思考,你会得出结论,对于JavaScript这样一个极其松散的动态环境来说,这是不自然的
因此,不要将时间和应用程序的性能浪费在实现不存在的构造上。只要专注于解决你的问题,而不是缺乏语言特征的问题。
现在问问自己:让所有成员都公开是什么伤害?
考虑到所说的一切,最终的解决方案将是:
class Person
constructor: (@name, @age, @alive) ->
@secret = 0
inc: -> @secret++
虽然它不会真正隐藏它们,但惯例是在"private"成员前面加一个下划线。这里的想法是,使用它的人应该假设这些成员是实现细节,并建议不要使用它们。
参考这个线程,您只能通过封闭的getter函数
以下是一个在大多数情况下都能满足要求的技巧:
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)必须是跨实例的唯一密钥。
试试
您实际上是在通过声明成员私有来隐藏实现细节。通过使用继承,您可以隐藏实现细节,通过声明一个"抽象"类(据我所知,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的函数实际上都应该返回一个bottleimpl(同时在注释中向用户隐藏这一事实)。不幸的是,当延长瓶子时,你不会延长瓶子_ impl,这可能不是你想要的。
hmmmmmmm不完全为真。如果你想要私人会员,你不能真正获得私人会员,但如果你真的真的想要,你可以拥有
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()
它们需要在构造的范围内才能工作。这是一个非常私人的地方。
问题私人member会减慢应用程序的速度。它需要在每次实例化时都运行,而不能只从原型中获取。玩得开心
你可以这样做。。。
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
或_
或您选择的任何东西来引用私有变量。
尽管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!
这是一个很有争议的话题。我个人喜欢隐藏一些属性和方法,以使类的契约更加清晰。
- 向模板实例变量传递调用方法调用的结果时出现异常
- Rails/Javascript:将实例变量传递给Coffeescript时发生Uncaught ReferenceEr
- 访问 javascript 对象的实例变量
- Angular2/Typescript:从链接可观察函数访问实例变量
- 如何在Promise回调中访问实例变量
- 如何使用每个ajax请求更新实例变量
- 实例变量变为未定义 - CoffeeScript
- 如何显式创建实例变量
- 如何在 JavaScript 中创建实例变量
- 模块化模式中的私有实例变量
- 将实例变量传递给 js Rails
- 找出实例变量名称本身
- 从视图中访问另一个操作实例变量
- 从视图访问实例变量
- 在主干模型中定义实例变量的正确方法是什么
- 是否可以在 javascript 中的私有函数中调用实例变量
- 将 rails 实例变量用于 javascript 条件
- 将实例变量替换为局部变量
- 为什么当我通过 Ajax 请求刷新部分时我的实例变量为空
- 实例变量