Tôi biết rằng đã hơn 1 thập kỷ kể từ khi điều này được hỏi, nhưng tôi chỉ suy nghĩ về điều này lần thứ n trong cuộc đời lập trình viên của mình và tìm thấy một giải pháp khả thi mà tôi chưa biết nếu tôi hoàn toàn thích . Tôi chưa thấy phương pháp này được ghi lại trước đây, vì vậy tôi sẽ đặt tên cho nó là "mẫu đô la riêng tư / công khai" hoặc mẫu _ $ / $ .
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]);
Khái niệm này sử dụng một ClassDefinition hàm trả về một Constructor hàm trả về một giao diện đối tượng. Phương thức duy nhất của giao diện là $
nhận một name
đối số để gọi hàm tương ứng trong đối tượng hàm tạo, bất kỳ đối số bổ sung nào được truyền sau khi name
được truyền trong lệnh gọi.
Hàm trợ giúp được xác định toàn cục ClassValues
lưu trữ tất cả các trường trong một đối tượng khi cần. Nó xác định _$
chức năng để truy cập chúng bằng cách name
. Điều này tuân theo một mẫu get / set ngắn để nếu value
được thông qua, nó sẽ được sử dụng làm giá trị biến mới.
var ClassValues = function (values) {
return {
_$: function _$(name, value) {
if (arguments.length > 1) {
values[name] = value;
}
return values[name];
}
};
};
Hàm được định nghĩa toàn cục Interface
sẽ lấy một đối tượng và một Values
đối tượng để trả về một _interface
hàm duy nhất $
kiểm tra obj
để tìm một hàm được đặt tên theo tham số name
và gọi nó values
là đối tượng có phạm vi . Các đối số bổ sung được truyền vào $
sẽ được truyền vào lời gọi hàm.
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;
};
Trong mẫu dưới đây, ClassX
được gán cho kết quả của ClassDefinition
, đó là Constructor
chức năng. Constructor
có thể nhận được bất kỳ số lượng đối số. Interface
là những gì mã bên ngoài nhận được sau khi gọi hàm tạo.
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;
}());
Không có điểm nào trong việc có các hàm không được tạo nguyên mẫu Constructor
, mặc dù bạn có thể định nghĩa chúng trong thân hàm hàm tạo. Tất cả các chức năng được gọi với mô hình đô la công khai this.$("functionName"[, param1[, param2 ...]])
. Các giá trị riêng được truy cập với mẫu đô la riêng this._$("valueName"[, replacingValue]);
. Như Interface
không có định nghĩa cho _$
, các giá trị không thể được truy cập bởi các đối tượng bên ngoài. Vì mỗi thân hàm được tạo nguyên mẫu this
được đặt thành values
đối tượng trong hàm $
, bạn sẽ có ngoại lệ nếu bạn gọi trực tiếp các hàm anh chị em của Trình xây dựng; mẫu _ $ / $ cũng cần phải được theo dõi trong các thân hàm nguyên mẫu. Dưới đây sử dụng mẫu.
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");
Và đầu ra giao diện điều khiển.
classX1.valA is invalid.
classX1.valA: undefined
classX1.valA is valid.
classX1.valA: v1
classX2.valA: v2
Mẫu _ $ / $ cho phép bảo mật hoàn toàn các giá trị trong các lớp được tạo mẫu đầy đủ. Tôi không biết liệu tôi có bao giờ sử dụng nó hay không, nếu nó có sai sót, nhưng này, nó là một câu đố hay!