2015-10-08 8 views
6

Ho un allineamentoCome passare il metodo definito il prototipo alla Array.map come callback

var arr = [' A ', ' b ', 'c']; 

e voglio trim gli spazi da ciascuna delle elemento dalla matrice.

può essere fatto utilizzando Array.map come

arr.map(function(el) { 
    return el.trim(); 
}); 

mi incuriosisce passando la funzione di trim/toLowerCase direttamente al map come funzione di callback, come arr.map(Math.max.apply.bind(Math.max, null)); per ottenere l'elemento massimo da ogni sottoarray o arr.map(Number); per castare ogni elemento su Numero.

Ho provato

arr.map(String.prototype.trim.apply); 

ma sta gettando errore

Uncaught TypeError: Function.prototype.apply was called on undefined, which is a undefined and not a function

Mi aspetto che String.prototype.trim.apply dovrebbe essere chiamato per ogni elemento della matrice con il contesto impostato l'elemento da array (passato a apply);

Ho anche provato diverse combinazioni di apply, call e bind senza successo.

  1. Perché la funzione sul prototipo non è possibile fare riferimento quando si utilizza map
  2. Come funzione può essere passato come parametro per map
+0

sono confusa sul motivo per cui arr.map (funzione ... Lavori mentre arr.map (String ... getta "arr non è definito." In – djechlin

+0

Firefox dice "TypeError:' Function.prototype.apply' chiamato incompatible 'undefined'". – Xufox

+0

var f = String.prototype.trim.call; f ('3'); genera errore, anche se String.prototype.trim .call ('3') funziona e typeof f === 'function'. Nessuna idea del perché. – djechlin

risposta

5
arr.map(String.prototype.trim.call.bind(String.prototype.trim)); 

call utilizza this internamente, che deve puntare alla funzione trim per funzionare correttamente in questo caso. Semplicemente passando String.prototype.trim.call lascerebbe call non associato a nessun metodo, risultante invece nel valore this che punta a window.

It works, but when used apply instead of call it throws error, arr.map(String.prototype.trim.apply.bind(String.prototype.trim));

Il problema è che map passerà 2 argomenti, l'elemento e l'indice. Quindi finisce per chiamare qualcosa come 'String.prototype.trim.apply('test', 0) che fallisce poiché il secondo argomento deve essere un array.

one more thing [' A ', ' B ', 'c'].map(String.prototype.trim.call.bind(String.prototype.toLowerCase));, in this, I've used trim.call and passed toLowerCase as context then why we need trim here, why trim is not called

Quando si utilizza call.bind il percorso che si è scelto di accedere alla funzione di riferimento call diventa irrilevante. La funzione che verrà chiamata è quella vincolata.

Se si desidera comporre funzioni insieme avrete bisogno di un approccio diverso:

var call = Function.prototype.call, 
    trim = call.bind(String.prototype.trim), 
    toLowerCase = call.bind(String.prototype.toLowerCase), 
    trimAndLowerCase = pipelineFrom(trim, toLowerCase); 

[' TeST '].map(trimAndLowerCase); 

function pipelineFrom(fn1, fn2) { 
    return function (val) { 
     return fn2(fn1(val)); 
    }; 
} 

Tuttavia a questo punto si sta meglio con:

arr.map(function (val) { 
    return val.trim().toLowerCase(); 
}); 
+0

Funziona, ma se usato 'apply' invece di' call' genera errore, 'arr.map (String.prototype. trim.apply.bind (String.prototype.trim)); ' – Tushar

+0

un'altra cosa' ['A', 'B', 'c']. map (String.prototype.trim.call.bind (String.prototype. toLowerCase)); ', in questo, ho usato' trim. call' e passa 'toLowerCase' come contesto, quindi perché abbiamo bisogno di' trim' qui, perché trim non è chiamato – Tushar

+1

@Tushar 'trim' non verrà chiamato perché lo hai usato come scorciatoia per ottenere un riferimento alla' chiamata ' funzione. La funzione che verrà chiamata è 'toLowerCase'. Ad esempio, potresti aver fatto 'Function.prototype.call.bind (String.prototype.toLowerCase)' e funzionerebbe anche. Come ottenere un riferimento alla funzione 'call' diventa irrilevante. – plalx

2

Questo funziona, è sicuro lungo -winded però:

var t = String.prototype.trim.call.bind(String.prototype.trim); 
arr.map(t); 

Perché è prolisso ci sono blog posts un d modules dedicato al non ricorrente, che è quello che stai cercando di fare qui.

ho fatto ask about this qui una volta ...

+0

Funziona, ma se usato 'apply' invece di' call' genera errore, 'arr.map (String.prototype.trim.apply.bind (String.prototype.trim));' – Tushar

+0

un'altra cosa '[' A ',' B ',' c ']. Map (String.prototype.trim.call.bind (String.prototype.toLowerCase)); ', in questo, ho usato' trim.call' e passato 'aLowerCase 'come contesto, quindi perché abbiamo bisogno di' trim' qui, perché trim non viene chiamato – Tushar

Problemi correlati