Bleh. Đó là một bummer lớn, bạn không thể quá tải các nhà điều hành lập chỉ mục trong JavaScript. Oh well. Chúng ta sẽ phải sáng tạo và đưa ra một giải pháp khác. Đây là một điều tốt (và vui). :-)
LLer, giải pháp bạn giải quyết là tốt nhất. Thanh danh. Thật thú vị khi gặp những người thực sự hiểu JavaScript ở mức độ đó.
Sau khi đọc câu hỏi này, tôi đã bị ấn tượng với một ý tưởng sử thi và đã viết một số mã cho niềm vui của nó. Giải pháp của tôi cho vấn đề này rất giống với giải pháp của bạn và nhiều vấn đề khác đã được thực hiện trước đây. Nhưng, tôi cảm thấy tôi đã nghĩ ra một thứ gì đó độc đáo và rất gọn gàng nên tôi muốn chia sẻ nó. Vì vậy, tôi đang lưu trữ một dự án của tôi trên CodePlex, nơi tôi sử dụng một kỹ thuật jQuery-esque để xác định các đặc tính (các hàm getter/setter khép kín) rất giống với cái bạn đang sử dụng. Đối với các giải pháp tôi đã đưa ra với tôi chỉ đơn giản là ngoại suy từ mã này đã tồn tại từ trước của tôi. Đây là cách tiếp cận của tôi đối với tải lười biếng của các chỉ mục mảng. Bắt đầu từ đầu ...
Hãy xem xét thuộc tính có tên "PageSize". Đây là cách các tài sản sẽ được sử dụng với kỹ thuật của tôi:
var MyClass = function() { }; // MyClass constructor.
var instance = new MyClass();
instance.PageSize(5);
alert(instance.PageSize());
chú ý rằng bất động sản là một chức năng duy nhất, nơi cung cấp một giá trị như các tham số đầu tiên gọi setter và rời ra tham số gọi các getter. Các "PageSize" bất động sản sẽ được định nghĩa như là một phần của lớp MyClass như sau:
MyClass.prototype.PageSize = function(v) { return this.GetSetProperty("PageSize", v, myFunctionThatDoesLazyLoading); };
chức năng sở hữu những chỉ đơn thuần là một wrapper quanh một cuộc gọi đến các phương pháp GetSetProperty utitily mà không thực tế nhận được và thiết lập.Đây là đoạn trích của hàm GetSetProperty:
Object.prototype.GetSetProperty = function(name, value, loadFunction) {
if (!this.Properties)
{
this.Properties = {};
}
if (value)
{
this.Properties[name] = value;
}
else
{
if (!this.Properties[name] && loadFunction)
{
this.Properties[name] = loadFunction();
}
return this.Properties[name]; // This will return "undefined" if property doesn't exist or the loadFunction wasn't provided.
}
};
Vì vậy, xử lý các thuộc tính. Nhưng, để cung cấp một phương tiện để truy cập vào các giá trị được lập chỉ mục của một tài sản có thể loại Mảng tôi sửa đổi mã này tiếp tục như vậy:
Object.prototype.GetSetProperty = function(name, value, loadFunction, index) {
if (!this.Properties)
{
this.Properties = {};
}
if (typeof index === "number" && this.Properties[name] && this.Properties[name].constructor == Array)
{
return this.GetSetArrayProperty(name, index, value, loadFunction);
}
else
{
value = index;
}
if (value)
{
this.Properties[name] = value;
}
else
{
if (!this.Properties[name] && loadFunction)
{
this.Properties[name] = loadFunction();
}
return this.Properties[name]; // This will return "undefined" if property doesn't exist or the loadFunction wasn't provided.
}
};
Object.prototype.GetSetArrayProperty = function(name, index, value, loadFunction) {
if (value)
{
this.Properties[name][index] = value;
}
else
{
if (!this.Properties[name][index] && loadFunction)
{
this.Properties[name][index] = loadFunction();
}
return this.Properties[name][index];
}
};
Việc kê khai nguyên mẫu sẽ cần phải được sửa đổi như sau:
MyClass.prototype.PageSize = function(i, v) { return this.GetSetProperty("PageSize", v, myFunctionThatDoesLazyLoading, i); };
mọi người đọc bài viết này có thể truy cập một tập làm việc của mã ở đây: http://jsbin.com/ajawe/edit
Dưới đây là một danh sách đầy đủ của mã với các xét nghiệm:
Object.prototype.GetSetProperty = function(name, value, loadFunction, index) {
if (!this.Properties)
{
this.Properties = {};
}
if (typeof index === "number" && this.Properties[name] && this.Properties[name].constructor == Array)
{
return this.GetSetArrayProperty(name, index, value, loadFunction);
}
else
{
value = index;
}
if (value)
{
this.Properties[name] = value;
}
else
{
if (!this.Properties[name] && loadFunction)
{
this.Properties[name] = loadFunction();
}
return this.Properties[name]; // This will return "undefined" if property doesn't exist or the loadFunction wasn't provided.
}
};
Object.prototype.GetSetArrayProperty = function(name, index, value, loadFunction) {
if (value)
{
this.Properties[name][index] = value;
}
else
{
if (!this.Properties[name][index] && loadFunction)
{
this.Properties[name][index] = loadFunction();
}
return this.Properties[name][index];
}
};
// Here's a nifty function that declares the properties for you.
Function.prototype.CreateProperty = function(propertyName, loadFunction) {
eval("this.prototype['" + propertyName.toString() + "'] = function(i, v) { return this.GetSetProperty('" + propertyName.toString() + "', v, " + eval(loadFunction) + ", i); };");
};
var myFunctionThatDoesLazyLoading = function() {
return "Ahoy!";
};
var MyClass = function() { }; // MyClass constructor.
MyClass.prototype.PageSize = function(i, v) { return this.GetSetProperty("PageSize", v, myFunctionThatDoesLazyLoading, i); };
var instance = new MyClass();
alert(instance.PageSize()); // PageSize is lazy loaded.
instance.PageSize(5); // PageSize is re-assigned.
alert(instance.PageSize()); // Returns the new value.
instance.PageSize([1, 2, 3]); // PageSize is re-assigned to have an Array value.
alert(instance.PageSize(2)); // Returns the value at index 2 of the Array value.
instance.PageSize(2, "foo"); // Re-assigns the value at index 2.
alert(instance.PageSize(2)); // Returns the new value at index 2.
MyClass.CreateProperty("NewProp", function() { return ["a", "b", "c"]; }); // Demo of the CreateProperty function.
alert(instance.NewProp());
alert(instance.NewProp(1));
Việc phân lớp đối tượng Array có được coi là tạo một "mảng giả" không? –
Có. Ngay cả khi bạn đã làm điều đó, một số cú pháp mảng chẳng hạn như cho trong sẽ không hoạt động. – fent
for..in không nên được sử dụng để lặp lại các mảng – Anurag