1

I like the Array.prototype.map method, and some time ago I came across a use of it I didn't expect.

    var xargByID = { a: 1, b: 2 };

    Array.prototype.map.bind(xargByID)(function (xarg) {

    });

I don't know how Array.prototype.map internally works so I have to ask, is it reliable? Might it break with time?

3 Answers 3

2

It simply not works. You can call Array.map only on Objects that have numerical properties starting with 0 and have a corresponding length property. So only this will work:

var xargByID = {0: 'first', 1: 'second', 2: 'third', length: 3};

Array.prototype.map.bind(xargByID)(function (xarg) {
    console.log(xarg);
});

It's because .map() internally does something like the following simulation:

function simulateMap(callback, thisArg) {
    var ret = [], length = this.length, that = thisArg || this;
    for (var i = 0; i < length; i++) {
        ret.push(callback.call(that, this[i], i, this));
    }
    return ret;
}

It's the same with .forEach(), .some(), and so on.

EDIT But if you like .map() so much you can do:

var xargByID = { a: 1, b: 2, c: 3};

Object.getOwnPropertyNames(xargByID).map(function(xarg, i, arr) {
    console.log(xarg, arr[i]);
});
Sign up to request clarification or add additional context in comments.

Comments

1

First off, .bind is definitely not the best way to write your example, much better would be Array.prototype.map.call(xargByID, function (xarg) {.

It will work as long as the object is array-like: it has a length property that is an integer >= 0, and the elements you want to iterate over are at properties that integers >= 0 and < the length. This is not a hack, it is by design; Array.prototype.map is made to be usable on non-Array objects, as long as they have that Array-like form.

In your example, it would not work, because the properties are not at numeric indexes and there is no length property. But it would work if xArgByID were, for example, this: {0: 'a', 1: 'b', length: 2}.

Comments

-1

I know that this doesn't answer the reliability aspect of your question, but if you have access to a library such as lodash then you can use its map function to iterate over an object. This is reliable.

_.map(collection, [iteratee=_.identity])

Creates an array of values by running each element in collection through iteratee. The iteratee is invoked with three arguments: (value, index|key, collection).

Depending on exactly what you want to do you may also want to consider the _.forOwn(), _.forIn() and _.forEach() methods. They also iterate over properties in an Object.

EDIT: As per cortopy's comment below I've updated this answer to be accurate for lodash 4.x. (The previous answer was accurate for lodash 3.x)

2 Comments

Which version of lodash? 4.6.1. doesn't accept a thisArg. I think you may be confusing it with the native Array.prototype.map() which does support a [thisArg] developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
@cortopy Yes this changed in lodash 4.x. I've updated the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.