나는 이것이 요청 된 지 10 년이 넘었 음을 알고 있지만 프로그래머 생활에서 n 번째로 이것에 대해 생각하고 아직 완전히 좋아하는지 알 수없는 해결책을 찾았습니다. . 이 방법론은 이전에 문서화되지 않았으므로 "private / public dollar pattern"또는 _ $ / $ pattern으로 이름을 지정 합니다.
var ownFunctionResult = this.$("functionName"[, arg1[, arg2 ...]]);
var ownFieldValue = this._$("fieldName"[, newValue]);
var objectFunctionResult = objectX.$("functionName"[, arg1[, arg2 ...]]);
//Throws an exception. objectX._$ is not defined
var objectFieldValue = objectX._$("fieldName"[, newValue]);
이 개념은 Interface 객체 를 반환하는 생성자 함수를 반환하는 ClassDefinition 함수를 사용 합니다. 인터페이스의 유일한 메소드는 생성자 객체에서 해당 함수를 호출 하는 인수를 수신하는 것입니다.$
name
name
입니다. 에 전달 된 는 호출에서 전달됩니다.
세계적으로 정의 도우미 함수는 ClassValues
모든 필드에 저장 필요에 따라 개체를. 로 액세스 하는 기능을 정의합니다 . 이것은 짧은 get / set 패턴을 따르므로 전달되면 새 변수 값으로 사용됩니다._$
name
value
var ClassValues = function (values) {
return {
_$: function _$(name, value) {
if (arguments.length > 1) {
values[name] = value;
}
return values[name];
}
};
};
전역 적으로 정의 된 함수 Interface
는 개체와 Values
개체를 사용 하여 매개 변수 뒤에 이름이 지정된 함수를 찾아 검사 하여 범위가 지정된 개체 로 호출하는 _interface
단일 함수 하나 를 반환 합니다. 전달 된 추가 인수 는 함수 호출시 전달됩니다.$
obj
name
values
$
var Interface = function (obj, values, className) {
var _interface = {
$: function $(name) {
if (typeof(obj[name]) === "function") {
return obj[name].apply(values, Array.prototype.splice.call(arguments, 1));
}
throw className + "." + name + " is not a function.";
}
};
//Give values access to the interface.
values.$ = _interface.$;
return _interface;
};
아래의 샘플에서 ClassX
의 결과에 할당 ClassDefinition
은 IS, Constructor
기능. Constructor
여러 개의 인수를받을 수 있습니다. Interface
생성자를 호출 한 후 외부 코드가 얻는 것입니다.
var ClassX = (function ClassDefinition () {
var Constructor = function Constructor (valA) {
return Interface(this, ClassValues({ valA: valA }), "ClassX");
};
Constructor.prototype.getValA = function getValA() {
//private value access pattern to get current value.
return this._$("valA");
};
Constructor.prototype.setValA = function setValA(valA) {
//private value access pattern to set new value.
this._$("valA", valA);
};
Constructor.prototype.isValAValid = function isValAValid(validMessage, invalidMessage) {
//interface access pattern to call object function.
var valA = this.$("getValA");
//timesAccessed was not defined in constructor but can be added later...
var timesAccessed = this._$("timesAccessed");
if (timesAccessed) {
timesAccessed = timesAccessed + 1;
} else {
timesAccessed = 1;
}
this._$("timesAccessed", timesAccessed);
if (valA) {
return "valA is " + validMessage + ".";
}
return "valA is " + invalidMessage + ".";
};
return Constructor;
}());
에 프로토 타입이 아닌 함수 Constructor
는 생성자 함수 본문에서 정의 할 수 있지만 아무 의미가 없습니다 . 모든 함수는 공개 달러 패턴으로 호출됩니다 this.$("functionName"[, param1[, param2 ...]])
. 개인 값은 개인 달러 패턴으로 액세스됩니다 this._$("valueName"[, replacingValue]);
. 에 Interface
대한 정의가 없으므로 _$
외부 객체에서 값에 액세스 할 수 없습니다. 프로토 타입 화 된 각 함수 본문이 function this
의 values
객체로 설정되어 있으므로 $
생성자 형제 함수를 직접 호출하면 예외가 발생합니다. _ $ / $ 패턴 의 요구가 너무 프로토 타입을 함수 몸에 따라야합니다. 아래 샘플 사용량.
var classX1 = new ClassX();
console.log("classX1." + classX1.$("isValAValid", "valid", "invalid"));
console.log("classX1.valA: " + classX1.$("getValA"));
classX1.$("setValA", "v1");
console.log("classX1." + classX1.$("isValAValid", "valid", "invalid"));
var classX2 = new ClassX("v2");
console.log("classX1.valA: " + classX1.$("getValA"));
console.log("classX2.valA: " + classX2.$("getValA"));
//This will throw an exception
//classX1._$("valA");
그리고 콘솔 출력.
classX1.valA is invalid.
classX1.valA: undefined
classX1.valA is valid.
classX1.valA: v1
classX2.valA: v2
_ $는 / $ 패턴은 완벽하게 프로토 타입 클래스의 값의 전체 개인 정보 보호를 할 수 있습니다. 내가 이것을 사용할 것인지, 결함이 있는지는 모르겠지만 좋은 퍼즐이었습니다!