patternjavascriptMinor
Hmm, a thoughtful library
Viewed 0 times
hmmlibrarythoughtful
Problem
I've been writing far too many routines in JavaScript that get a record from a an object or array based off a matching property, much like jQuery does with DOM elements. Since all the good names are taken, I called it
I went with the philosophy that if I don't need it yet, I wont provide for it.
``
var array = [], map = {}, json;
this.forEach( function( value ){
if( value instanceof Object ){
json = JSON.stringify( value );
if( !map[json] ){
array.push( value );
map[json] = true;
}
}
else if( !~array.indexOf( value ) ){
array.push( value );
}
});
return array;
}
function Hmm( data )
{ //data could be a string -> treat as JSON, parse it
//data could be an object, or a string that got converted to an object -> convert to array
//data could be an array ( original or through conversion ) -> leave as is
this.data = data instanceof Object ? data : JSON.parse( data );
this.data = this.data instanceof Array ? this.data : [ this.data ];
}
Hmm.prototype.index = function( name )
{ //Name can have dots, 'car.tire.brand.name' should get the expected
//Generates an index object
var index = {} , i;
this.data.forEach( function( value )
{
var key = getNamedValue( value , name ),
keys = key instanceof Array ? key : [key];
for( i = 0 ; i < keys.length ; i++ )
{
key = keys[i];
index[key] = index[key] || [];
index[key].push( value );
}
Hmm.I went with the philosophy that if I don't need it yet, I wont provide for it.
``
var Hmm = (function()
{ //A snippet/library to find records in table-like JS arrays
function getNamedValue( o , name )
{ //Name can have dots, 'car.tire.brand.name' should get the expected
var parts = name.split(".");
while( parts.length && o ){
o = o[parts.shift()];
}
return o;
}
function unique( )
{ //Assuming this is an array, will copy all unique entries of this` to a returned new arrayvar array = [], map = {}, json;
this.forEach( function( value ){
if( value instanceof Object ){
json = JSON.stringify( value );
if( !map[json] ){
array.push( value );
map[json] = true;
}
}
else if( !~array.indexOf( value ) ){
array.push( value );
}
});
return array;
}
function Hmm( data )
{ //data could be a string -> treat as JSON, parse it
//data could be an object, or a string that got converted to an object -> convert to array
//data could be an array ( original or through conversion ) -> leave as is
this.data = data instanceof Object ? data : JSON.parse( data );
this.data = this.data instanceof Array ? this.data : [ this.data ];
}
Hmm.prototype.index = function( name )
{ //Name can have dots, 'car.tire.brand.name' should get the expected
//Generates an index object
var index = {} , i;
this.data.forEach( function( value )
{
var key = getNamedValue( value , name ),
keys = key instanceof Array ? key : [key];
for( i = 0 ; i < keys.length ; i++ )
{
key = keys[i];
index[key] = index[key] || [];
index[key].push( value );
}
Solution
It's very nice. What few qualms I have are a result of me looking really hard for things to have qualms about (furrowing my brow and going "hmm", basically).
Anyway, some thoughts:
-
Your
-
Similarly edge-case'y: Your
-
The
A
-
That curly-brace-on-new-line style just rubs me the wrong way, but you know what you're doing, so I'll spare you the "automatic semi-colon insertion" speech :)
On a more overall note: Like jQuery, it might be useful to always return a
Anyway, some thoughts:
-
Your
unique function relies on the assumption that there are no circular references in the object passed to JSON.stringify. It's probably a fair assumption, but an assumption nonetheless. Also, from a specification standpoint, JSON representation of objects doesn't impose or guarantee any ordering of properties. I highly doubt it'll ever be an issue anywhere, but it could mean that identical objects will have different JSON representations, and unique would thus include both those objects.-
Similarly edge-case'y: Your
instanceof usage is vulnerable to the usual cross-frame pitfalls.-
The
!~array.indexOf( value ) trick is a bit arcane. It's neat, but I don't think I've actually seen it used anywhere - except in some other code you posted :)A
=== -1 comparison isn't nearly as cool, but it wouldn't cause me to go "huh?". In other words: I like it, but I wouldn't call it obvious or idiomatic.-
That curly-brace-on-new-line style just rubs me the wrong way, but you know what you're doing, so I'll spare you the "automatic semi-colon insertion" speech :)
On a more overall note: Like jQuery, it might be useful to always return a
Hmm-wrapped array, instead of only adding unique to the array returned by collect. Of course it'd be quite a different API.Context
StackExchange Code Review Q#49152, answer score: 6
Revisions (0)
No revisions yet.