누군가 CoffeeScript에서 비공개 비 정적 멤버를 만드는 방법을 알고 있습니까? 현재 저는 이것을하고 있는데, 클래스 외부에서 사용해서는 안된다는 것을 명확히하기 위해 밑줄로 시작하는 공용 변수를 사용합니다.
class Thing extends EventEmitter
constructor: (@_name) ->
getName: -> @_name
클래스에 변수를 넣으면 정적 멤버가되지만 어떻게 비 정적으로 만들 수 있습니까? “멋지다”지 않고도 가능합니까?
답변
“멋지다”지 않고도 가능합니까?
슬프게도, 당신은 멋져 야 합니다.
class Thing extends EventEmitter
constructor: (name) ->
@getName = -> name
기억 “그냥 자바 스크립트입니다.”
답변
클래스는 함수일 뿐이므로 범위를 만듭니다. 이 범위 내에 정의 된 모든 것은 외부에서 볼 수 없습니다.
class Foo
# this will be our private method. it is invisible
# outside of the current scope
foo = -> "foo"
# this will be our public method.
# note that it is defined with ':' and not '='
# '=' creates a *local* variable
# : adds a property to the class prototype
bar: -> foo()
c = new Foo
# this will return "foo"
c.bar()
# this will crash
c.foo
coffeescript는 이것을 다음과 같이 컴파일합니다.
(function() {
var Foo, c;
Foo = (function() {
var foo;
function Foo() {}
foo = function() {
return "foo";
};
Foo.prototype.bar = function() {
return foo();
};
return Foo;
})();
c = new Foo;
c.bar();
c.foo();
}).call(this);
답변
더 멋진 걸 보여주고 싶어
class Thing extends EventEmitter
constructor: ( nm) ->
_name = nm
Object.defineProperty @, 'name',
get: ->
_name
set: (val) ->
_name = val
enumerable: true
configurable: true
이제 할 수 있습니다
t = new Thing( 'Dropin')
# members can be accessed like properties with the protection from getter/setter functions!
t.name = 'Dragout'
console.log t.name
# no way to access the private member
console.log t._name
답변
Vitaly의 대답에는 한 가지 문제가 있으며 범위에 고유 하고 싶은 변수를 정의 할 수 없다는 것입니다. 그렇게 개인 이름을 만든 다음 변경하면 이름 값이 클래스의 모든 인스턴스에 대해 변경됩니다. 그 문제를 해결할 수있는 한 가지 방법이 있습니다
# create a function that will pretend to be our class
MyClass = ->
# this has created a new scope
# define our private varibles
names = ['joe', 'jerry']
# the names array will be different for every single instance of the class
# so that solves our problem
# define our REAL class
class InnerMyClass
# test function
getNames: ->
return names;
# return new instance of our class
new InnerMyClass
사용하지 않는 한 외부에서 이름 배열에 액세스하는 것은 불가능하지 않습니다. getNames
이것을 테스트
test = new MyClass;
tempNames = test.getNames()
tempNames # is ['joe', 'jerry']
# add a new value
tempNames.push 'john'
# now get the names again
newNames = test.getNames();
# the value of newNames is now
['joe', 'jerry', 'john']
# now to check a new instance has a new clean names array
newInstance = new MyClass
newInstance.getNames() # === ['joe', 'jerry']
# test should not be affected
test.getNames() # === ['joe', 'jerry', 'john']
컴파일 된 자바 스크립트
var MyClass;
MyClass = function() {
var names;
names = ['joe', 'jerry'];
MyClass = (function() {
MyClass.name = 'MyClass';
function MyClass() {}
MyClass.prototype.getNames = function() {
return names;
};
return MyClass;
})();
return new MyClass;
};
답변
여기에 몇 가지 다른 답변과 https://stackoverflow.com/a/7579956/1484513을 추가하는 솔루션이 있습니다 . 프라이빗 인스턴스 (비 정적) 변수를 프라이빗 클래스 (정적) 배열에 저장하고 객체 ID를 사용하여 해당 배열의 어느 요소에 각 인스턴스에 속하는 데이터가 포함되어 있는지 파악합니다.
# Add IDs to classes.
(->
i = 1
Object.defineProperty Object.prototype, "__id", { writable:true }
Object.defineProperty Object.prototype, "_id", { get: -> @__id ?= i++ }
)()
class MyClass
# Private attribute storage.
__ = []
# Private class (static) variables.
_a = null
_b = null
# Public instance attributes.
c: null
# Private functions.
_getA = -> a
# Public methods.
getB: -> _b
getD: -> __[@._id].d
constructor: (a,b,@c,d) ->
_a = a
_b = b
# Private instance attributes.
__[@._id] = {d:d}
# Test
test1 = new MyClass 's', 't', 'u', 'v'
console.log 'test1', test1.getB(), test1.c, test1.getD() # test1 t u v
test2 = new MyClass 'W', 'X', 'Y', 'Z'
console.log 'test2', test2.getB(), test2.c, test2.getD() # test2 X Y Z
console.log 'test1', test1.getB(), test1.c, test1.getD() # test1 X u v
console.log test1.a # undefined
console.log test1._a # undefined
# Test sub-classes.
class AnotherClass extends MyClass
test1 = new AnotherClass 's', 't', 'u', 'v'
console.log 'test1', test1.getB(), test1.c, test1.getD() # test1 t u v
test2 = new AnotherClass 'W', 'X', 'Y', 'Z'
console.log 'test2', test2.getB(), test2.c, test2.getD() # test2 X Y Z
console.log 'test1', test1.getB(), test1.c, test1.getD() # test1 X u v
console.log test1.a # undefined
console.log test1._a # undefined
console.log test1.getA() # fatal error
답변
여기 내가 설정에 대해 발견 된 최고의 기사 public static members
, private static members
, public and private members
, 및 기타 관련 물건. 그것은 많은 정보와 커버 js
대의 coffee
비교. 그리고 역사적인 이유로 여기에 최고의 코드 예제가 있습니다.
# CoffeeScript
class Square
# private static variable
counter = 0
# private static method
countInstance = ->
counter++; return
# public static method
@instanceCount = ->
counter
constructor: (side) ->
countInstance()
# side is already a private variable,
# we define a private variable `self` to avoid evil `this`
self = this
# private method
logChange = ->
console.log "Side is set to #{side}"
# public methods
self.setSide = (v) ->
side = v
logChange()
self.area = ->
side * side
s1 = new Square(2)
console.log s1.area() # output 4
s2 = new Square(3)
console.log s2.area() # output 9
s2.setSide 4 # output Side is set to 4
console.log s2.area() # output 16
console.log Square.instanceCount() # output 2
답변
Coffeescript에서 비공개 비 정적 멤버를 선언하는 방법은 다음과 같습니다.
전체 참조는 https://github.com/vhmh2005/jsClass 에서 확인할 수 있습니다.
class Class
# private members
# note: '=' is used to define private members
# naming convention for private members is _camelCase
_privateProperty = 0
_privateMethod = (value) ->
_privateProperty = value
return
# example of _privateProperty set up in class constructor
constructor: (privateProperty, @publicProperty) ->
_privateProperty = privateProperty