最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

functional programming - Javascript map native object methods - Stack Overflow

programmeradmin1浏览0评论

In Python, you can something like this:

>>> list(map(str.upper, ['foo','bar']))
['FOO', 'BAR']

I would like to be able to do something similar in javascript:

I've tried the following in Chrome using the native map implementation ( ):

['foo','bar'].map(String.prototype.toUpperCase)

['foo','bar'].map(String.prototype.toUpperCase.call)

Why doesn't call work? Is there any elegant way to do this or must I wrap toUpperCase in a callback function? Thx

In Python, you can something like this:

>>> list(map(str.upper, ['foo','bar']))
['FOO', 'BAR']

I would like to be able to do something similar in javascript:

I've tried the following in Chrome using the native map implementation ( https://developer.mozilla/en/JavaScript/Reference/Global_Objects/Array/map ):

['foo','bar'].map(String.prototype.toUpperCase)

['foo','bar'].map(String.prototype.toUpperCase.call)

Why doesn't call work? Is there any elegant way to do this or must I wrap toUpperCase in a callback function? Thx

Share Improve this question asked Nov 12, 2010 at 18:28 BaversjoBaversjo 3,7163 gold badges37 silver badges49 bronze badges 1
  • toUpperCase.call doesn't work because call is resolved against Function.prototype and so is not related to toUpperCase. It looks at this to figure out which method is being called, and the way map invokes the function, this is undefined. – Mike Samuel Commented Nov 12, 2010 at 18:39
Add a ment  | 

5 Answers 5

Reset to default 2

Try:

['foo','bar'].map(Function.prototype.call.bind(String.prototype.toUpperCase))

or for the same effect:

['foo','bar'].map(Function.call.bind("".toUpperCase))

JavaScript's treatment of this is a bad trip.

Modern browsers support this (although it is a recent addition)

var a = ['foo','bar'];
var b = a.map(String.toUpperCase);

alert(b[1]);

or even

var a = ['foo','bar'].map(String.toUpperCase);
alert(a[0]);

example: http://www.jsfiddle/xPsba/

That is because String.prototype.toUpperCase runs on this (Context) object but map function can't set the array element as context. It passes it as an argument. A workaround would be

['foo','bar'].map(function(k) { return String.prototype.toUpperCase.call(k) });

You're all missing the point. :-)

We want to call a method (not a function) on all elements of an array. You can use map:

a.map(function(x){x.frob()})

but that's too much typing. We want to say:

a.mapm(A.frob)

where A is the class of the elements of a and mapm is a new Array method that calls its argument method on each element of this (array a in this case). You could define mapm thus:

Array.prototype.mapm = function (method)
{
    return this.map(function (x) { return method.apply(x) } )
};

and call it thus:

["a", "b", "c"].mapm("".toUpperCase)    ==>     ["A", "B", "C"]

The only problem is that you've added a new element, mapm to every array, though it's ignored by most Array methods, e.g. length and map.

You can use something like this:

function map(arr, fn){
    var i = 0, len = arr.length, ret = [];
    while(i < len){
        ret[i] = fn(arr[i++]);
    }
    return ret;
}

And to use it:

var result = map(['foo', 'bar'], function(item) {
    return item.toUpperCase();
});

console.log ( result ); // => ['FOO', 'BAR']
发布评论

评论列表(0)

  1. 暂无评论