Gast23: Referenz auf native Funktion führt zu Fehler

Hallo,

Bisher war ich immer der Meinung, dass

var foo = obj.fun;  
foo();

das gleiche tut wie

obj.fun();

Nun muss ich aber feststellen, dass dieser Code in sämtlichen Browsern zu Fehlern führt (in Oopspera sogar zum Absturz...):

var now = new Date();  
var gt = now.getTime;  
gt();

Dies hier funktioniert aber:

var now = new Date();  
(now.getTime)();

Was hab ich hier nicht verstanden bzw. wo gibts dazu Dokus?

Danke

  1. var foo = obj.fun;

    foo();

    
    >   
    > das gleiche tut wie  
    >   
    > `obj.fun();`{:.language-javascript}  
      
    Nein, der Unterschied ist, dass die Methode bei obj.fun() im Kontext von obj ausgeführt wird, im Falle von foo() in keinem Kontext (entspricht dem globalen Kontext).  
      
    
    > ~~~javascript
    
    var now = new Date();  
    
    > var gt = now.getTime;  
    > gt();
    
    

    Die Funktion wird hier im Kontext von window aufgerufen, weil du sie vom Date-Objekt entkoppelst.

    Es ist nicht mehr die Methode getTime an der Date-Instanz now, sondern einfach die losgelöste prototypisch vererbte Methode Date.prototype.getTime. Wenn sie aber keinem Date-Objekt mehr anhängt und der this-Verweis somit nicht funktioniert, nützt dir der Methodenaufruf nichts.

    Was der JavaScript-Interpreter hier intern macht bei der Ausführung von gt(), ist nichts anderes als:
    Date.prototype.getTime.call(window)
    Und das ist Unsinn, weil die Methode nicht auf dem Objekt window operieren kann.

    Es gibt in JavaScript keine inhärente Zugehörigkeit einer Funktion zu einem Objekt. Speicherst du eine Referenz auf das Funktionsobjekt in einer Variable und rufst die Funktion dann über diese Referenz auf anstatt über objekt.methode(), ist der Bezug zum Objekt verloren gegangen. Diese besteht nur in dem Fall, dass du objekt.methode() notierst.

    Den Kontext kann man korrigieren bzw. absichtlich »fälschen«, indem man die Methoden call bzw. apply von Funktionsobjekten nutzen kann. Man kann Lamda-Funktionen erzeugen, die den Kontext korrigieren.

    Wie das genau aussieht, hängt davon ab, was du genau vorhast. Was hast du genau vor? Suchst du so etwas?

    var date = new Date;
    var gt = function () { return date.getTime() }; /* Closure */
    gt();

    Oder funktionaler mit bind:

    var gt = date.getTime.bind(date);
    gt();

    Siehe beides http://aktuell.de.selfhtml.org/artikel/javascript/organisation/

    Mathias

    1. Hey Mathias,

      vielen Dank für die ausführliche Antwort! So genau wollt ich es gar nicht wissen. :D

      Was hast du genau vor? Suchst du so etwas?

      Nein, eigentlich suchte ich das hier:

        var now = new Date();  
        var gt = now.getTime;  
        gt.call(now); // oder gt.apply(now);
      

      call und apply kenne ich eigentlich schon, aber das:

      Die Funktion wird hier im Kontext von window aufgerufen, weil du sie vom Date-Objekt entkoppelst.

      ...war mir nicht so 100%ig klar.

      Duck und weg.

    2. Ein kleiner Nachtrag:

      Es ist nicht mehr die Methode getTime an der Date-Instanz now, sondern einfach die losgelöste prototypisch vererbte Methode Date.prototype.getTime.

      Ist es nicht eher eine Kopie der Instanz-Methode? Per default ist das natürlich Date.prototype.getTime, aber theoretisch kann man die überschreiben*:

        var now = new Date();  
        now.getTime = function() { return '"this" is: ' + this; };  
        var gt = now.getTime;  
        now.getTime = function() { return Date.prototype.getTime.call(this); };  
        
        gt();  
        gt.call(now);  
        now.getTime();
      

      * don't try this at home, kids! ;)