Reputation: 1884
Looking for another eye on making the following Javascript more efficient.
The following JSON is produced from a Resteasy service:
var testing = {
"com:klistret:cmdb:ci:pojo:successful":true,
"com:klistret:cmdb:ci:pojo:count":1,
"com:klistret:cmdb:ci:pojo:elements":{
"com:klistret:cmdb:ci:pojo:id":123,
"com:klistret:cmdb:ci:pojo:name":"Mars",
"com:klistret:cmdb:ci:pojo:type":{
"com:klistret:cmdb:ci:pojo:id":1,
"com:klistret:cmdb:ci:pojo:name":"Environment"
},
"com:klistret:cmdb:ci:pojo:configuration":{
"@www:w3:org:2001:XMLSchemainstance:type":"Environment",
"@Watermark":"past",
"com:klistret:cmdb:ci:commons:Name":"Mars"
}
}
};
Extended the Extjs JSONReader to handle key depths higher than 2 in the createAccessor method. Wondering if there is a way to make the code more efficient? The function below will be called like function(testing, "com:klistret:cmdb:ci:pojo:configuration.@Watermark")
where the com:klistret:cmdb:ci:pojo:elements
property is the root.
createAccessor : function(){
var re = /[\[\.]/;
return function(expr) {
if(Ext.isEmpty(expr)){
return Ext.emptyFn;
}
if(Ext.isFunction(expr)){
return expr;
}
# THIS FUNCTION I WANT TO BE EFFICIENT
return function(obj){
while (String(expr).search(re) !== -1) {
var i = String(expr).search(re);
var key = expr.substring(0, i);
if (obj.hasOwnProperty(key)) {
obj = obj[key];
}
expr = expr.substring(i+1, expr.length);
}
return obj[expr];
};
};
}()
Upvotes: 1
Views: 554
Reputation: 8376
This is what I use. I only allow dot annotation, mind:
Ext.override(Ext.data.JsonReader, {
createAccessor: function() {
return function(expr) {
if (Ext.isEmpty(expr)) {
return Ext.emptyFn;
} else if (Ext.isFunction(expr)) {
return expr;
} else {
return function(obj) {
var parts = (expr || '').split('.'),
result = obj,
part,
match;
while (parts.length > 0 && result) {
part = parts.shift();
match = part.match(/^(.+?)(\[(\d+)\])?$/);
result = result[match[1]];
if (result && match[3]) {
result = result[match[3]];
}
}
return result;
}
}
};
}()
});
Upvotes: 1
Reputation: 24577
A basic optimization would be to avoid scanning the string twice with search
, which is pretty slow.
The best you could do is replace all the string scanning and substring extraction with a single call to expr.split('.')
, which would support accessors of the form aaa.bbb.ccc.ddd
and turn them into an array like ['aaa','bbb','ccc','ddd']
. The other two characters you seem to support ([
and ]
) wouldn't work.
Alternately, you could do an initial match for /[^\].[]+/g
over your entire string and keep the matches to obtain a similar array, but this would possibly be slower than the previous solution.
Upvotes: 1