Object map() / transmute() method

I'm somewhat curious on peoples opinion about such a method. I Actually didn't find anything similar in librarys I use on regular bases so far.

This is my implementation:

Object.map = function _map( obj, transform ) {
if( typeof obj === 'object' && typeof transform === 'function' ) {
Object.keys( obj ).forEach(function _forEach( key ) {
(function _mapping( oldkey, transmuted ) {
if( transmuted && transmuted.length ) {
obj[ transmuted[ 0 ] || oldkey ] = transmuted[ 1 ];

if( transmuted[ 0 ] && oldkey !== transmuted[ 0 ] ) {
delete obj[ oldkey ];
}
}
}( key, transform.apply( obj, [ key, obj[ key ]] ) ));
});
}
};


I normally put it on the Object object and not the prototype. However, usage is like this

var foo = {
someProp: 5,
bar: 10,
moar: 20
};

Object.map( foo, function(key, value) {
return [ key.toUpperCase(), value*2 ];
});


result:

Object { SOMEPROP=10, BAR=20, MOAR=40}


I most often use it to translate CSS properties (to vendor prefixes). But I don't see people use an approach like this often in ECMAscript. Any thoughts?

-
I would implement it as such. I'd also avoid the word "map". And probably use word "transform". It's also a rare operation and simple to do without a utility function so most people probably do this by hand –  Raynos Nov 22 '11 at 1:15
As for other libraries, jQuery.each() does exactly that. –  konijn Jan 21 at 18:45

First comment, there is no need for the closure inside _forEach which makes the code unnecessarily difficult to read. More importantly I would argue that the function would be much more useful if did not transform the original object and instead returned a new object.

Object.map = function (obj, mapping) {
var mapped = {};

if (typeof obj !== 'object') {
return mapped;
}

if (typeof mapping !== 'function') {
// We could just return obj but that wouldn't be
// consistent with the rest of the interface which always returns
// a new object.
mapping = function (key, val) {
return [ key, val ];
};
}

Object.keys( obj ).forEach(function (key) {
var transmuted = mapping.apply(obj, [ key, value ]);

if (transmuted && transmuted.length) {
mapped[ transmuted[0] || key ] = kv[ 1 ];
}
});

return mapped;
};


This is not only less dangerous for widely available object but it also makes the function more flexible by allowing it to be chained or used within an expression:

Object.map(oldCss, function (key, value) {
// ...
}).doSomethingElse();


At the very least I would have your original function return the passed in object to allow for chaining or use within an expression.

-