Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

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?

share|improve this question
    
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
add comment

1 Answer

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.