2012-05-16 13 views
28

ich das Gegenteil von dem Get JavaScript function-object from its name as a string?Name als String aus einer JavaScript-Funktionsreferenz?

tun möchten Das heißt, gegeben:

function foo() 
{} 

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

bar(foo); 

Wie erhalte ich den Namen der Funktion hinter einer Referenz?

+0

'var bittet = foo; bar (bat) '- was soll es nun drucken? – Alnitak

+1

@Alnitak. Es sollte 'foo' gedruckt werden. das ist der Funktionsname. 'bat' ist eine Variable mit Bezug auf die Funktion' foo'. – gdoron

+0

Was passiert, wenn der Callback keinen Namen hat? - dh 'bar (function() {...});' – Spudley

Antwort

24

Wenn Sie myFunction.name Sie nicht verwenden, dann können:

// 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]; 
}; 

Oder für moderne Browser, die don Unterstützung der name Eigenschaft (do sie existieren) fügen Sie diesen:

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, jetzt habe ich es, die '(' wenn für die 'exec' Übereinstimmung, nicht ein Teil der Regex. cool. +1 . BTW, warum es 'foo) nicht alarmiert?'? – gdoron

+0

Warum passt es nicht 'foo) {...'? – gdoron

+1

@gdoron Da Regex Zeichen aufeinander folgend bis zum Ende übereinstimmen muss. Die 'Funktion' in der Regex startet die Übereinstimmung und verbraucht dann null oder mehr beliebige, aber keine Zeichen (so viele wie möglich).Sobald es das getan hat, muss es aufhören; Es kann keine Nichtübereinstimmungen überspringen und weitermachen. – Phrogz

13
var name = callback.name; 

MDN:

Der Name-Eigenschaft gibt den Namen einer Funktion, oder eine leere Zeichenfolge für anonyme Funktionen:

merken gerade diese Eigenschaft nicht Standard.

Live DEMO

+1

'[Der Name] Eigenschaft ist nicht Standard' ist nicht mehr wahr, es ist in ECMA 6.0/2015: http://www.ecma-international.org/ecma-262/6.0/#sec-setfunctionname/Siehe auch http: //www.2ality.com/2015/09/funktionsnamen-es6.html – CoDEmanX

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

versuchen, die .name Eigenschaft zuzugreifen:

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

Eleganter Regex als meins; nett :) Sind Sie sicher, dass alle Browser nach der führenden 'Funktion' ein Leerzeichen setzen? – Phrogz

+0

@Phrogz Ich bin zuversichtlich genug, das oben genannte nicht zu ändern. Wenn es einen Randfall gibt, würde dies sowieso nur die anonyme Funktion beeinflussen, und "bar" könnte leicht angepasst werden, um dies zu berücksichtigen. – kojiro

+0

Nachdem ich Ihren Code gesehen habe, erinnere ich mich an die Spezifikation für die normalisierte String-Darstellung und IIRC der Platz ist erforderlich. – Phrogz

0

Wenn Sie die Funktion auf ein bestimmtes Objekt Ereignis gesucht haben, kann dies helfen:

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

Sie den Namen Objekt und Funktion extrahieren mit:

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

Zum Beispiel:

function MyObject() 
{ 
} 

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

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

Das wird wahrscheinlich funktionieren, aber ist es nicht viel teurer, einen Stack-Trace zu erstellen, als 'this.toString()' zu analysieren? – Gili

+0

Ja, aber ich verwende das nur für Debug-Nachrichten. Die obigen Antworten würden nur "hi" zurückgeben, das "MyObject.hi" zurückgibt. –

+1

Das ist wirklich gut zum Debuggen. Danke oder teilen! – Raisch

0

für mich, nur mit einer kleinen Änderung (Hinzufügen \ vor Elternteil), diese Arbeit:

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]; 
    } 
    }); 
}