2012-05-16 12 views
28

Voglio fare l'opposto di Get JavaScript function-object from its name as a string?Ottieni il nome come stringa da una funzione di riferimento Javascript?

Cioè, dato:

function foo() 
{} 

function bar(callback) 
{ 
    var name = ???; // how to get "foo" from callback? 
} 

bar(foo); 

Come faccio ad avere il nome della funzione dietro un riferimento?

+0

'var bat = foo; bar (bat) '- ora cosa dovrebbe stampare? – Alnitak

+1

@Alnitak. Dovrebbe stampare 'pippo'. questo è il nome della funzione. 'bat' è una variabile con un riferimento alla funzione' pippo'. – gdoron

+0

cosa succede se il callback non ha un nome? - es. 'bar (function() {...});' – Spudley

risposta

24

Se non è possibile utilizzare myFunction.name allora si può:

// Add a new method available on all function values 
Function.prototype.getName = function(){ 
    // Find zero or more non-paren chars after the function start 
    return /function ([^(]*)/.exec(this+"")[1]; 
}; 

O per i browser moderni che don supportare la proprietà name (do esistono) aggiungerlo direttamente:?

if (Function.prototype.name === undefined){ 
    // Add a custom property to all function values 
    // that actually invokes a method to get the value 
    Object.defineProperty(Function.prototype,'name',{ 
    get:function(){ 
     return /function ([^(]*)/.exec(this+"")[1]; 
    } 
    }); 
} 
+0

Ohhh, ora ho capito, il '(' se per la corrispondenza 'exec', non una parte della regex. cool. +1 BTW, perché non allerta 'foo)'? – gdoron

+0

Perché non corrisponde a 'foo) {...'? – gdoron

+1

@gdoron Perché l'espressione regolare deve corrispondere ai caratteri in sequenza finché non si arresta. La 'funzione' nella regex inizia la corrispondenza, e quindi consuma zero o più nulla-ma-a- (caratteri (il maggior numero possibile).Una volta fatto, deve fermarsi; non può "saltare" le non-partite e continuare. – Phrogz

13
var name = callback.name; 

MDN:

La proprietà nome restituisce il nome di una funzione o una stringa vuota per funzioni anonime:

solo notare che questa proprietà è non di serie.

Live DEMO

+1

'[la proprietà nome non è standard' non è più vera, è in ECMA 6.0/2015: http://www.ecma-international.org/ecma-262/6.0/#sec-setfunctionname/Vedere anche http: //www.2ality.com/2015/09/function-names-es6.html – CoDEmanX

1
var x = function fooBar(){}; 
console.log(x.name); 
// "fooBar" 
0

tenta di accedere alla proprietà .name:

callback.name 
4
function bar(callback){ 
    var name=callback.toString(); 
    var reg=/function ([^\(]*)/; 
    return reg.exec(name)[1]; 
} 

>>> function foo() { }; 
>>> bar(foo); 
"foo" 
>>> bar(function(){}); 
"" 
+0

Più elegante regex del mio, bello :) Sei sicuro che tutti i browser metteranno uno spazio dopo la funzione 'principale'? – Phrogz

+0

@Phrogz Sono abbastanza sicuro di non cambiare quanto sopra. Se c'è un caso limite, ciò influenzerebbe comunque solo la funzione anonima e "bar" potrebbe essere facilmente regolato per tenerne conto. – kojiro

+0

Dopo aver visto il tuo codice, ricordo di aver guardato le specifiche molto tempo fa per la rappresentazione della stringa normalizzata e IIRC lo spazio è richiesto. – Phrogz

0

Se stavate cercando per la funzione su un evento specifico oggetto, questo può aiutare:

var a = document.form1 
a.onsubmit.name 
2

è possibile estrarre il nome dell'oggetto e la funzione con:

function getFunctionName() 
{ 
    return (new Error()).stack.split('\n')[2].split(' ')[5]; 
} 

Ad esempio:

function MyObject() 
{ 
} 

MyObject.prototype.hi = function hi() 
{ 
    console.log(getFunctionName()); 
}; 

var myObject = new MyObject(); 
myObject.hi(); // outputs "MyObject.hi" 
+0

Probabilmente funzionerà, ma non è molto più costoso costruire una traccia dello stack piuttosto che analizzare "this.toString()'? – Gili

+0

Sì, ma lo sto usando solo per i messaggi di debug. Le risposte di cui sopra restituirebbero solo "ciao" questo restituisce "MyObject.hi". –

+1

Questo è molto utile per il debug. Grazie o condivisione! – Raisch

0

per me, con solo una piccola modifica (aggiungendo \ prima del genitore), questo lavoro:

if (Function.prototype.name === undefined){ 
    // Add a custom property to all function values 
    // that actually invokes a method to get the value 
    Object.defineProperty(Function.prototype,'name',{ 
    get:function(){ 
     return /function ([^\(]*)/.exec(this+"")[1]; 
    } 
    }); 
} 
Problemi correlati