javascript länge - Wie bekomme ich den Funktionsnamen von dieser Funktion?




title tag (15)

schau hier: http://www.tek-tips.com/viewthread.cfm?qid=1209619

arguments.callee.toString();

scheint für Ihre Bedürfnisse richtig zu sein.

Wie kann ich auf einen Funktionsnamen innerhalb dieser Funktion zugreifen?

// parasitic inheritance
var ns.parent.child = function() {
  var parent = new ns.parent();
  parent.newFunc = function() {

  }
  return parent;
}

var ns.parent = function() {
  // at this point, i want to know who the child is that called the parent
  // ie
}

var obj = new ns.parent.child();

ES6 (inspiriert von sendy halim's Antwort unten):

myFunction.name

Erläuterung zu MDN . Ab 2015 funktioniert in Nodejs und allen gängigen Browsern außer IE.

Hinweis: Bei gebundenen Funktionen gibt dies " bound <originalName> ". Sie müssen die "Grenze" entfernen, wenn Sie den ursprünglichen Namen erhalten möchten.

ES5 (inspiriert von Vlads Antwort):

Wenn Sie einen Verweis auf die Funktion haben, können Sie Folgendes tun:

function functionName( func )
{
    // Match:
    // - ^          the beginning of the string
    // - function   the word 'function'
    // - \s+        at least some white space
    // - ([\w\$]+)  capture one or more valid JavaScript identifier characters
    // - \s*        optionally followed by white space (in theory there won't be any here,
    //              so if performance is an issue this can be omitted[1]
    // - \(         followed by an opening brace
    //
    var result = /^function\s+([\w\$]+)\s*\(/.exec( func.toString() )

    return  result  ?  result[ 1 ]  :  '' // for an anonymous function there won't be a match
}
  • Ich habe keine Unit-Tests oder verifizierte Implementierungsunterschiede durchgeführt, aber im Prinzip sollte es funktionieren, wenn nicht einen Kommentar hinterlassen.
  • Hinweis: Funktioniert nicht mit gebundenen Funktionen
  • Hinweis: caller und callee gelten als veraltet.

[1] Ich führe es hier ein, weil es legal ist und oft genug Syntax-Highlighting-Tools den weißen Zwischenraum zwischen Funktionsnamen und Klammern nicht berücksichtigen. Auf der anderen Seite ist mir keine Implementierung von .toString () bekannt, die hier Leerzeichen enthält, weshalb Sie sie weglassen können.

Als Antwort auf die ursprüngliche Frage würde ich parasitäre Vererbung fallen lassen und für einige traditionellere OOP-Entwurfsmuster gehen. Ich schrieb ein TidBits.OoJs um komfortabel OOP-Code in JavaScript mit einem Feature-Set zu schreiben, das C ++ nachahmt (noch nicht vollständig, aber meistens).

Ich sehe aus den Kommentaren, dass Sie vermeiden möchten, dass Informationen über die parent über den Konstruktor ausgegeben werden. Ich muss zugeben, dass traditionelle Designmuster Sie nicht davor bewahren werden, da es allgemein als eine gute Sache angesehen wird, Ihre Abhängigkeiten offensichtlich und erzwungen zu machen.

Ich würde auch vorschlagen, von anonymen Funktionen abzulenken. Sie machen nur das Debugging und Profiling einer PITA, weil alles nur als "anonyme Funktion" angezeigt wird, und es gibt keinen Vorteil für sie, den ich kenne.


Was Sie tun, ist unbenannte Funktion zu einer Variablen zuzuweisen. Wahrscheinlich brauchen Sie stattdessen einen benannten Funktionsausdruck ( http://kangax.github.com/nfe/ ).

var x = function x() {
    console.log( arguments.callee.name );
}
x();

aber ich bin mir nicht sicher, wie viel Cross-Browser das ist; Es gibt ein Problem mit IE6, das das Namensleck der Funktion in den äußeren Bereich bringt. arguments.callee ist ebenfalls veraltet und führt zu einem Fehler, wenn Sie den strict mode .


Sie können die name -Eigenschaft verwenden, um den Funktionsnamen abzurufen, sofern Sie keine anonyme Funktion verwenden

Beispielsweise:

var Person = function Person () {
  this.someMethod = function () {};
};

Person.prototype.getSomeMethodName = function () {
  return this.someMethod.name;
};

var p = new Person();
// will return "", because someMethod is assigned with anonymous function
console.log(p.getSomeMethodName());

Jetzt versuchen wir es mit der benannten Funktion

var Person = function Person () {
  this.someMethod = function someMethod() {};
};

Jetzt können Sie verwenden

// will return "someMethod"
p.getSomeMethodName()

Sie könnten dies verwenden, aber es ist nicht für alle Browser, nur diejenigen, die Error.stack unterstützen

function VamosRafa(){ 
  var a = new Error().stack.match(/at (.*?) /);
  console.log(a[1]);
} 
VamosRafa();

Natürlich ist dies für die aktuelle Funktion, aber Sie bekommen die Idee.

Prost!


Ich weiß, dass dies eine alte Frage ist, aber in letzter Zeit hatte ich ein ähnliches Problem, als ich versuchte, die Methoden einiger React Components zu Debugging-Zwecken zu dekorieren. Wie bereits erwähnt, sind arguments.caller und arguments.callee im strikten Modus verboten, der wahrscheinlich standardmäßig in React tranpiling aktiviert ist. Sie können es entweder deaktivieren, oder ich konnte einen weiteren Hack erstellen, da in React alle Klassenfunktionen benannt sind, können Sie Folgendes tun:

Component.prototype.componentWillMount = function componentWillMount() {
    console.log('Callee name: ', this.__proto__.constructor.toString().substr(0,30));
...
}

Es sieht aus wie das blödeste Ding, das ich in meinem Leben geschrieben habe, aber es ist lustig: D

function getName(d){
  const error = new Error();
  const firefoxMatch = (error.stack.split('\n')[0 + d].match(/^.*([email protected])/) || [])[0];
  const chromeMatch = ((((error.stack.split('at ') || [])[1 + d] || '').match(/(^|\.| <| )(.*[^(<])( \()/) || [])[2] || '').split('.').pop();
  const safariMatch = error.stack.split('\n')[0 + d];

  // firefoxMatch ? console.log('firefoxMatch', firefoxMatch) : void 0;
  // chromeMatch ? console.log('chromeMatch', chromeMatch) : void 0;
  // safariMatch ? console.log('safariMatch', safariMatch) : void 0;

  return firefoxMatch || chromeMatch || safariMatch;
}

d - Stapeltiefe. 0 - gebe diesen Funktionsnamen, 1 - Eltern usw. zurück;
[0 + d] - nur um zu verstehen - was passiert;
firefoxMatch - funktioniert für Safari, aber ich hatte wirklich ein wenig Zeit zum Testen, weil Mac's Besitzer nach dem Rauchen zurückgekommen ist und mich vertrieben hat: '(

Testen:

function limbo(){
  for(let i = 0; i < 4; i++){
    console.log(getName(i));
  }
}
function lust(){
  limbo();
}
function gluttony(){
  lust();
}

gluttony();

Ergebnis:
Chrom:

Fitefox:

Diese Lösung wurde nur zum Spaß erstellt ! Benutze es nicht für echte Projekte. Es hängt nicht von der ES-Spezifikation ab, es hängt nur von der Browser-Realisierung ab. Nach dem nächsten Chrome / Firefox / Safari Update kann es kaputt gehen.
Mehr als das gibt es keine Fehler (ha) Verarbeitung - wenn d mehr als Stack-Länge sein wird - Sie werden einen Fehler erhalten;
Für andere wowsers Fehler message Muster - Sie erhalten einen Fehler;
Es muss für ES6-Klassen .split('.').pop() ( .split('.').pop() ), aber Sie können einen Fehler bekommen;


Ich hatte ein ähnliches Problem und habe es wie folgt gelöst:

Function.prototype.myname = function() {
   return this.toString()
       .substr( 0, this.toString().indexOf( "(" ) )
       .replace( "function ", "" ); 
}

Dieser Code implementiert auf bequemere Weise eine Antwort, die ich bereits oben in dieser Diskussion gelesen habe. Jetzt habe ich eine Memberfunktion, die den Namen eines Funktionsobjekts abruft. Hier ist das vollständige Skript ...

<script language="javascript" TYPE="text/javascript">

    Function.prototype.myname = function() { 
        return this.toString()
            .substr( 0, this.toString().indexOf( "(" ) )
            .replace("function ", "" ); 
    }
    function call_this( _fn ) { document.write( _fn.myname() ); }
    function _yeaaahhh() { /* do something */ }
    call_this( _yeaaahhh ); 

</script>

Einfacher Weg, den Funktionsnamen von der Funktion zu erhalten, die Sie gerade ausführen.

function x(){alert(this.name)};x()


Jeder constructor legt einen Eigenschaftsnamen name , der den Funktionsnamen darstellt. Sie greifen auf den constructor über eine Instanz (unter Verwendung von new ) oder einen prototype :

function Person() {
  console.log(this.constructor.name); //Person
}

var p = new Person();
console.log(p.constructor.name); //Person

console.log(Person.prototype.constructor.name);  //Person

Du kannst nicht. Funktionen haben keine Namen gemäß dem Standard (obwohl Mozilla ein solches Attribut hat) - sie können nur Variablen mit Namen zugewiesen werden.

Auch dein Kommentar:

// access fully qualified name (ie "my.namespace.myFunc")

befindet sich in der Funktion my.namespace.myFunc.getFn

Sie können den Konstruktor eines Objekts, das von new erstellt wurde, zurückgeben

So könnte man sagen

var obj = new my.namespace.myFunc();
console.info(obj.constructor); //my.namespace.myFunc

Dies könnte für Sie funktionieren:

function foo() { bar(); }

function bar() { console.log(bar.caller.name); }

Running foo () wird "foo" oder undefined ausgeben, wenn Sie von einer anonymen Funktion aufrufen.

Es funktioniert auch mit Konstruktoren, in diesem Fall würde es den Namen des aufrufenden Konstruktors ausgeben (zB "Foo").

Weitere Informationen finden Sie hier: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/Caller

Sie behaupten, dass es nicht Standard ist, aber auch, dass es von allen gängigen Browsern unterstützt wird: Firefox, Safari, Chrome, Opera und IE.


Sie könnten Function.name :

In den meisten Implementierungen von JavaScript können Sie, sobald Sie den Verweis Ihres Konstruktors im Gültigkeitsbereich haben, den String-Namen von seiner name-Eigenschaft abrufen (z. B. Function.name oder Object.constructor.name)

Sie könnten Function.callee :

Die native Methode " arguments.caller " ist veraltet, aber die meisten Browser unterstützen Function.caller , wodurch das eigentliche aufrufende Objekt (sein Code) zurückgegeben wird: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FFunction%2Fcaller

Sie könnten eine Quellkarte erstellen :

Wenn Sie die Literalfunktionssignatur (den "Namen") benötigen und nicht das Objekt selbst, müssen Sie möglicherweise auf etwas mehr angepasstes zugreifen, wie zum Beispiel das Erstellen eines Array-Verweises der API-String-Werte, die Sie benötigen häufig zugreifen. Sie können sie zusammen mit Object.keys() und Ihrem String-Array Object.keys() oder in Mozillas Source Maps-Bibliothek auf GitHub nachsehen, für größere Projekte: https://github.com/mozilla/source-map


In ES5 ist das Beste, was zu tun ist:

function functionName(fun) {
  var ret = fun.toString();
  ret = ret.substr('function '.length);
  ret = ret.substr(0, ret.indexOf('('));
  return ret;
}

Die Verwendung von Function.caller ist nicht Standard. Function.caller und arguments.callee sind beide im strikten Modus verboten.

Edit: Nus Regex-basierte Antwort unten erreicht das gleiche, hat aber eine bessere Leistung!

In ES6 können Sie einfach myFunction.name .

Hinweis: Achten Sie darauf, dass einige JS-Minifier Funktionsnamen wegwerfen, um besser komprimieren zu können. Sie müssen möglicherweise ihre Einstellungen optimieren, um dies zu vermeiden.


Angular1

Für AngularJS , die AngularJS , kann diese Situation mit verwendet werden Promises.

Here heißt es:

Versprechungen können verwendet werden, um asynchrone Funktionen zu verwirren und ermöglichen es, mehrere Funktionen miteinander zu verketten.

Sie können eine schöne Erklärung finden here auch.

Beispiel in den unten genannten docs .

  promiseB = promiseA.then(
    function onSuccess(result) {
      return result + 1;
    }
    ,function onError(err) {
      //Handle error
    }
  );

 // promiseB will be resolved immediately after promiseA is resolved 
 // and its value will be the result of promiseA incremented by 1.

Angular2 und später

In Angular2mit Blick auf das folgende Beispiel, aber seine recommended zu verwenden Observablesmit Angular2.

 search(term: string) {
     return this.http
  .get(`https://api.spotify.com/v1/search?q=${term}&type=artist`)
  .map((response) => response.json())
  .toPromise();

}

Sie können das auf diese Weise konsumieren,

search() {
    this.searchService.search(this.searchField.value)
      .then((result) => {
    this.result = result.artists.items;
  })
  .catch((error) => console.error(error));
}

Siehe den original Beitrag hier. TypScript unterstützt jedoch keine nativen es6 Promises . Wenn Sie es verwenden möchten, benötigen Sie dazu möglicherweise ein Plugin.

Zusätzlich werden hier die Versprechen spec .





javascript function