在Javascript中设置函数的最佳方法(可能是通过闭包?)
我有一个web应用程序,它调用一个web服务,返回一些表示对象数组的JSON。每个对象都有一些字段。下面是一些JSON示例:在Javascript中设置函数的最佳方法(可能是通过闭包?),javascript,json,performance,closures,memory-efficient,Javascript,Json,Performance,Closures,Memory Efficient,我有一个web应用程序,它调用一个web服务,返回一些表示对象数组的JSON。每个对象都有一些字段。下面是一些JSON示例: { "data": [ { "id": "12345", "from": { "name": "John Doe", "id": "6789" }, "start_time": "2012-12-16T02:17:20+0000",
{
"data": [
{
"id": "12345",
"from": {
"name": "John Doe",
"id": "6789"
},
"start_time": "2012-12-16T02:17:20+0000",
"end_time": "2012-12-16T02:17:20+0000",
"publish_time": "2012-12-16T02:17:20+0000"
}
},
{
"id": "8888",
"from": {
"name": "Jane Smith",
"id": "011"
},
"start_time": "2012-12-16T02:17:20+0000",
"end_time": "2012-12-17T02:17:20+0000",
"publish_time": "2012-12-16T02:17:20+0000"
}
}
]
}
返回后,我使用jQuery的parseJSON()方法将其膨胀为一个对象数组(保留“data”值)。这一切都很好,但在我有了阵列之后,我有了几个可以在每个阵列插槽上操作的函数。例如,假设有一个名为GetDuration()的函数,它将打印结束时间和开始时间之间的时间间隔。在任何情况下,我定义了几个函数(可能是15个),在这一点上,我只是在整个数组中迭代,并使用函数的副本膨胀每个对象。范例
for (var i=0;i<data.length;i++)
data[i].TimeLapse = function() { ... };
for(var i=0;i我想你说的是,你想用JSON来设置不同类型对象的属性,每个对象都有自己的方法?不清楚你在追求什么,或者目前正在做什么。但是如果我是对的,你肯定做错了
简言之,不要向数据中添加函数。相反,请使用可在创建时接受数据的方法创建类
// Constructor, accepts an object expected to have data about a user
var User = function(data) {
// save a field from the passed in user data on this instance
this.name = data.name;
};
// a method every User object will have that uses some bit of user data
User.prototype.sayHi = function() {
alert('Hi, my name is ' + this.name);
};
// A place to put our new user objects
var users = [];
// An array of objects to iterate through
var jsonData = [
{name: 'Joe'},
{name: 'Sally'}
];
// Iterate through the array
for (var i = 0; i < jsonData.length; i++) {
// make a user, passing the constructor the data object for that user
users.push( new User(jsonData[i]) );
}
users[0].sayHi(); // alerts: "Hi, my name is Joe"
users[1].sayHi(); // alerts: "Hi, my name is Sally"
//构造函数,接受预期包含用户数据的对象
var User=函数(数据){
//保存此实例上传入的用户数据中的字段
this.name=data.name;
};
//每个用户对象将拥有的一种方法,它使用一些用户数据
User.prototype.sayHi=函数(){
警报(‘嗨,我的名字是’+这个名字);
};
//放置新用户对象的位置
var用户=[];
//要迭代的对象数组
var jsonData=[
{姓名:'乔'},
{姓名:'Sally'}
];
//遍历数组
对于(var i=0;i
正如其他人在评论中所写,不清楚您想要什么,但这听起来与您所描述的最接近:
function make_duration_fun(x) {
return function() { return GetDuration(x.start_time, x.end_time); };
}
然后,您的循环可以执行以下操作:
data[i].TimeLapse = make_duration_fun(data[i]);
只有一个duration函数,但每次调用make_duration\u fun
时,都会得到一个新的闭包,该闭包使用相同的函数和不同的x
绑定
如果必须循环每个数据元素,为什么不计算每个项目的持续时间并将其作为属性添加
如果您愿意将每个数据对象的所有属性复制到一个新的数据对象,您可以在该对象的构造函数上使用原型,并向原型中添加诸如timeLapse
之类的函数。然后,所有数据对象都通过原型继承连接起来工作。但这是一项额外的工作,可能无法执行曼特
您可以使用JSONP或执行返回代码的变体,而不是直接使用JSON
{
"data": [
new DataItem(
12345",
{
"name": "John Doe",
"id": "6789"
},
"2012-12-16T02:17:20+0000",
"2012-12-16T02:17:20+0000",
"2012-12-16T02:17:20+0000"
),
// ... and so on ...
]
}
与直接向上对象表示法(禁止执行代码,只允许有值)相反,您必须小心执行代码,但我相信这样做是安全的。例如,您可以不说newdataitem()
只需为每个最终对象嵌入一个数组,然后在其上循环并使用,apply
ing和new
关键字将数组转换为对象,并将项目数组传递到DataItem
,以获得新的原型有线对象
在数据
数组中的每个项目中添加函数,理论上可能会占用比所需更多的内存。根据您要权衡的时间和空间,还有其他选项。例如:
function ItemWrapper(dataobj) {
for (key in dataobj) {
if (!dataobj.hasOwnProperty(key)) { continue; }
this[key] = dataobj[ky];
}
this.timeLapse = (new Date(this.end_time)).getTime() - (new Date(this.start_time)).getTime(); // assign simple static properties
}
ItemWrapper.prototype.dynamicFn = function () {
return this.x - this.y; // changeable properties accessed as functions
}
var currentObj = new ItemWrapper(data[23]);
console.log(currentObj.timeLapse); // static
console.log(currentObj.dynamicFn()); //dynamic
问题是:您希望在使用时还是在解析时执行此包装?在解析时执行此操作实际上是我的建议#2。但此建议仅在您需要特定项目时执行。我不知道您的项目访问模式,因此这可能不理想,但至少是一个选项
使用应用
或调用
:
function timeLapse() {
return (new Date(this.end_time)).getTime() - (new Date(this.start_time)).getTime();
}
var Item16Elapsed = timeLapse.apply(data[16]);
通过这种方式,您不会到处附加函数,也不会将对象转换为新的原型有线对象,但您必须以稍微不同的方式调用对象
你能给出一个更完整的例子来说明你是如何使用这些函数的吗?它们是如何传递数据的,它们返回什么?如果我们看不到你目前是如何做的,很难给出建议。JSON越少,代码就越多。正如@AlexWayne所说,我们真的不能给出任何建议,这取决于你试图做什么和完成什么。然而,如果您已经设置好了函数,我只是将其设置为常规函数,然后执行类似于data[I].TimeLapse=GetDuration(data[I].start\u time,data[I].end\u time)的操作;
闭包仅在“保留对定义它们的环境的绑定”的情况下才有帮助.我不知道这会有什么帮助。正如亚历克斯·韦恩(Alex Wayne)所说,一个完整的(最低限度的)示例会有很大帮助。感谢大家提供的有用答案,如果我的问题缺乏细节,我很抱歉。我已经开始进行更改。根据Erik的评论,我注意到一些可以简单地用属性替换的函数。进行此更改,我希望能获得内存和效率的提升(无需跳转堆栈)。在这方面有一个折衷:如果数据发生更改,则属性将反映过期的值。但是,对于某些属性来说,这不是问题,因此这是一个值得折衷的折衷。对于其他一些情况,保留函数是有意义的,因为数据可以更改,并且…我希望反映最新的数据。为了提供更多详细信息,函数(和属性)是通过KnockoutJS绑定到的。因此有属性、函数和一些KO.Computed函数。有趣的是,KO.Computed有一个称为“deferEvaluation”的功能(这是自解释的)。当应用该功能时,可能还有一些额外的内存