我正在尝试将延迟计算的元素添加到数组中。这意味着它们的值在它们被访问之前是不会被计算或知道的。这类似于previous question I asked,但用于对象。
我最终为对象所做的是
Object.prototype.lazy = function(var_name, value_function) {
this.__defineGetter__(var_name, function() {
var saved_value = value_function();
this.__defineGetter__(var_name, function() {
return saved_value;
});
return saved_value;
});
}
lazy('exampleField', function() {
// the code that returns the value I want
});但我还没有想出一种方法来实现实数组。数组没有这样的setter。您可以将一个函数推送到一个数组中,但您必须将其作为一个函数来调用,以便它返回您真正想要的对象。我现在要做的是创建一个对象,并将其视为数组。
Object.prototype.lazy_push = function(value_function) {
if(!this.length)
this.length = 0;
this.lazy(this.length++, value_function);
}所以我想知道的是,有没有办法做到这一点,同时仍然是在一个数组上,而不是在一个伪数组上?
更新:只有当value_function返回原始数据类型时,以下函数才有效。
Array.prototype.lazy_push = function(value_function) {
var a = this,
i = this.length;
this.push({
toString: function() {
return a[i] = value_function();
}
});
}如果您尝试推送一个对象,例如其中包含属性的对象,则在直接访问该对象之前,您将无法访问这些属性。这不会发生在setter中,这就是为什么我想要一些Javascript的设置语法。现在,我将使用伪数组,这对于我正在做的事情来说已经足够了。
发布于 2010-06-10 23:53:20
没有。不幸的是,这是一件大事。
发布于 2010-06-13 00:15:40
好吧,除非我误解了你的问题,否则我相信我已经找到了一个简单的解决方案,它不需要所谓的"lazy_push“函数。
按照我上一个答案中的方法,创建一个MyArray类:
function MyArray(){
this.object = [];
}
MyArray.prototype.push = function(what){
this.object.push(what);
}现在最重要的部分是getter函数,我们将创建一个getIdx()函数来获取数组中的值。然后,该函数使用'typeof‘运算符来确定返回值是否为函数。如果是,则返回函数返回的值,如果不是,则返回原始值。
代码更有意义:
MyArray.prototype.getIdx = function(which){
if(typeof this.object[which] == 'function'){
alert("a function");
//NOTICE THE '()' AT THE END OF THE NEXT LINE!!!
return this.object[which]();
}
return this.object[which];
}希望如果我没有完全回答你的问题,你可以从这里弄清楚。
<-我的原创帖子->
这不是一个真正的答案,但有几个要点。
//使用对象变量创建构造函数,//该对象变量包含您希望扩展函数MyArray(){ this.object = [];}//创建引用对象的本机函数的函数MyArray.prototype.push = function(what){ this.object.push(what);} //Etc...等等……等等……
为本机对象函数编写所有的访问器方法不一定很有趣,但它保证了Javascript引擎的安全。
发布于 2010-06-11 20:55:01
不是吧。在JavaScript中不能重载索引器操作符是一个很大的缺点。哦,好吧。我们只需要有创意,想出一个不同的解决方案。这是一件好事(也很有趣)。:-)
LLer,你解决的方案是非常好的。太棒了。遇到真正了解JavaScript的人是令人耳目一新的。
读完这个问题后,我有了一个史诗般的想法,并写了一些代码来娱乐它。我对这个问题的解决方案与您的解决方案以及其他许多以前做过的解决方案非常相似。但是,我觉得我想出了一些独特的,非常整洁的东西,所以我想分享它。
因此,我在CodePlex上托管了一个我的项目,其中我使用了一种非常类似jQuery的技术来定义属性(自包含的getter/setter函数),与您正在使用的非常相似。对于我想出的解决方案,我只是简单地从我的这段预先存在的代码中推断出来。下面是我对延迟加载数组索引的方法。从头开始...
让我们考虑一个名为"PageSize“的属性。下面是如何在我的技术中使用该属性:
var MyClass = function() { }; // MyClass constructor.
var instance = new MyClass();
instance.PageSize(5);
alert(instance.PageSize());请注意,该属性是一个单独的函数,其中提供一个值作为第一个参数将调用setter,省略该参数将调用getter。"PageSize“属性将被定义为MyClass类的一部分,如下所示:
MyClass.prototype.PageSize = function(v) { return this.GetSetProperty("PageSize", v, myFunctionThatDoesLazyLoading); };属性函数只是对utitily方法调用的包装,该方法执行实际的获取和设置。下面是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.
}
};这样就可以处理属性了。但是,为了提供访问Array类型的可能属性的索引值的方法,我进一步修改了这段代码,如下所示:
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];
}
};需要像这样修改原型声明:
MyClass.prototype.PageSize = function(i, v) { return this.GetSetProperty("PageSize", v, myFunctionThatDoesLazyLoading, i); };阅读本文的每个人都可以在这里访问代码的工作集:http://jsbin.com/ajawe/edit
下面是带有测试的代码的完整清单:
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));https://stackoverflow.com/questions/2952573
复制相似问题