2010-11-12 7 views
3

En Python, vous pouvez quelque chose comme ceci:carte Javascript méthodes d'objet natif

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

Je voudrais pouvoir faire quelque chose de similaire en javascript:

J'ai essayé ce qui suit dans Chrome en utilisant la mise en œuvre de la carte native (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map):

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

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

Pourquoi ne pas appeler le travail? Existe-t-il une manière élégante de faire ceci ou dois-je emballer toUpperCase dans une fonction de rappel? Thx

+0

'toUpperCase.call' ne fonctionne pas car' call' est résolu par rapport à 'Function.prototype' et n'est donc pas lié à' toUpperCase'. Il regarde 'this' pour savoir quelle méthode est appelée, et la façon dont' map' appelle la fonction, 'this' est' undefined'. –

Répondre

1

Les navigateurs modernes prennent en charge ce (although it is a recent addition)

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

alert(b[1]); 

ou même

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

exemple: http://www.jsfiddle.net/xPsba/

+0

Cela fonctionne dans Firefox 4 mais pas en chrome 7 sur mac. Je suppose que je vais devoir l'envelopper dans une fonction :) – Baversjo

+1

Cela ne fonctionnera pas sur un autre navigateur que Firefox parce que 'String.toUpperCase' est une * extension Mozilla *, ne fait pas partie de la norme ECMAScript (note qui peut être à tort confondus avec 'String.prototype.toUpperCase'), ils appellent ces méthodes" statiques "" Array et String Generics "et je ne pense pas vraiment que d'autres implémenteurs les incluront .... – CMS

+0

@CMS, ça marche sur FF, IE , Chrome, Safari et Opera pour Windows .. –

-1

Vous pouvez utiliser quelque chose comme ceci:

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

Et pour l'utiliser:

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

console.log (result); // => ['FOO', 'BAR'] 
+0

Avez-vous des exemples d'utilisation? Je préfère utiliser la fonction de carte native. – Baversjo

+0

Il n'est pas encore largement disponible – Mic

+0

une boucle for serait beaucoup plus simple: p –

1

C'est parce que String.prototype.toUpperCase fonctionne sur objet this (contexte) mais map fonction ne peut pas définir l'élément de tableau en tant que contexte. Il le passe comme un argument. Une solution serait

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

encore mieux est d'ignorer complètement la partie prototype et de l'utiliser comme ['' foo ',' bar ']. Map (String.toUpperCase); 'qui s'exécute dans le bon contexte. –

1

Essayez:

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

ou pour le même effet:

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

traitement de JavaScript de this est un mauvais voyage.

1

Vous manquez tous le point. :-)

Nous voulons appeler une méthode (pas une fonction) sur tous les éléments d'un tableau. Vous pouvez utiliser map:

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

mais c'est trop taper. Nous voulons dire:

a.mapm(A.frob) 

A est la classe des éléments de a et mapm est une nouvelle méthode Array qui appelle sa méthode d'argument sur chaque élément de this (tableau a dans ce cas).Vous pouvez définir mapm ainsi:

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

et l'appeler ainsi:

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

Le seul problème est que vous avez ajouté un nouvel élément, mapm à chaque tableau, si elle est ignorée par la plupart des Array méthodes , par exemple length et map.

+0

+1 pour comprendre le point. Bien sûr, dans les cas où votre code devra jouer correctement avec un autre code, modifier le prototype de Array est risqué, donc peut-être une légère modification pour permettre quelque chose comme: 'a.map (method (" toUpperCase ")); function method (m) {return function (x) {return x [m]();}} 'De plus, une amélioration mineure pourrait aussi vous permettre de passer certains paramètres pour la méthode via' method' –

Questions connexes