2016-03-26 5 views
8

Kann jemand bitte erklären, warum das Definieren einer Prototyp-Funktion mit Lambda-Ausdruck nicht funktioniert? Ich dachte, das muss vorher gefragt werden, konnte es aber nicht finden.Warum kann Lambda nicht verwendet werden, um Prototyp-Funktion zu definieren

function Book(title, year) { 
    this.title = title; 
    this.year = year; 

    // define a function within the object, which works fine 
    this.printYear =() => console.log("instance function of an object: " + this.year); 
} 

dies nicht funktioniert

Book.prototype.printTitle2 =() => { 
     console.log(this.title); 
    } 

und dies ist natürlich in Ordnung:

Book.prototype.printTitle = function() { 
     console.log(this); 
     console.log(this.title); 
    } 
+1

Fett Pfeile haben keine' this' – georg

+0

@georg ich denke, es ist aber einfach nicht, was ich dachte, es wäre. – stt106

+0

@ stt106: georgs Kommentar ist richtig, außer dass es zwei Wörter fehlt: "a" und "binding": "Pfeile haben keine' this' Bindung. " Eine "Bindung" ist der Mechanismus, den die JavaScript-Spezifikation verwendet, um über das Auflösen von Dingen wie 'this', Variablennamen und Konstantennamen zu sprechen. Zum Beispiel hat eine Funktion, die eine Variable mit dem Namen "a" deklariert, eine * Bindung * für diese Variable (indirekt über einen env-Eintrag). Normale Funktionen haben eine * Bindung * für 'this', die auf einen Wert gesetzt wird, wenn sie aufgerufen werden, aber Pfeilfunktionen nicht, weshalb sie über die 'this'-Bindung des Kontextes, in dem sie erstellt wurden, schließen . –

Antwort

11

Eines der Hauptmerkmale von Pfeilfunktionen ist, dass sie über die this aus dem Kontext schließen, in dem sie erstellt werden; Sie bekommen es nicht basierend darauf, wie sie aufgerufen werden, wie andere Funktionen es tun. So ...

// ...whatever `this` is *here* 
Book.prototype.printTitle2 =() => { 
    // ...is what `this` will be *here* 
    console.log(this.title); 
}; 

Aber Ihre Funktion beruht auf this Unterschiedlich je nachdem, wie es heißt.

Dies ist kein Anwendungsfall für Pfeilfunktionen. Verwenden Sie eine normale Funktion:

Book.prototype.printTitle2 = function() { 
    console.log(this.title); 
}; 

Oder noch besser, verwenden Sie die neue class Syntax:

class Book { 
    constructor(title, year) { 
     this.title = title; 
     this.year = year; 
    } 

    printTitle2() { 
     console.log(this.title); 
    } 
} 
7

Die Arrow function würde der Kontext this gehört zum Umfang beheben, bei dem die Funktion definiert wurde. Ich glaube, Sie haben diese Funktion in window Bereich definiert. So wird der this auf window in Ihrer Funktion zeigen.

Sie können normal hier verwenden. Und wir müssen vorsichtig sein, wenn wir Pfeilfunktionen verwenden.

+0

Danke und das macht jetzt Sinn; aber ich werde die andere Antwort akzeptieren, da sie ein bisschen mehr Einsicht bietet; Ich hoffe, es würde dir nichts ausmachen. – stt106

+0

@ stt106 Sie können das tun. Froh, übrigens zu helfen :) –

0

Neben @t-j-crowder ‚s answer, wollte ich einen Testfall (Mokka assert), die Sie verlassen kann visualisieren, was nicht funktioniert.

Sie können auch mehr über den Umfang der Pfeil Funktionen lesen Sie hier: You Don't Know JS von Kyle Simpson, der this im Detail erklärt.

Grundsätzlich zeigt eine Pfeilfunktion this auf den umgebenden Kontext des aktuellen Kontextes, was praktisch ist, wenn Sie umschließende Funktionen haben. Was es tut ist im Grunde die var self = this; Sache.

Oder wie Kyle sagt:

[...] Lexical this in Pfeilcallback-Funktion im vorherigen Schnipsel jetzt wie in der umschließenden makeRequest(..) Funktion auf den gleichen Wert zeigt. Mit anderen Worten, => ist ein syntaktischer Ersatz für var self = this.

In Fällen, in denen var self = this (oder alternativ eine Funktion .bind(this) Aufruf) normalerweise hilfreich wäre, sind => Pfeilfunktionen eine bessere Alternative, die nach dem gleichen Prinzip funktioniert. [...

]

Sie können es testen, sich mit meinem Kern: https://gist.github.com/jay-bricksoft/96738dd8a48ceb9f517e914b834cc1ee

In meinem Testfall war die Ausgabe:

Lambda 
    function(){} 
     √ should equal function´s type 
     1) should have equal context as function 
     2) should be able to be used as constructor 
    1 passing (39ms) 
    2 failing 
    1) Lambda function(){} should have equal context as function: 
     AssertionError: 'undefined' == 'string' 
     + expected - actual 
     -undefined 
     +string 

     at Context.<anonymous> (test\index.js:29:14) 
    2) Lambda function(){} should be able to be used as constructor: 
    TypeError: construct_l is not a constructor 
     at Context.<anonymous> (test\index.js:34:20) 

EDIT: hinzugefügt Beispiel/Verweis auf Kyle Simpson „You Don ‚t ES6" Know https://github.com/getify/You-Dont-Know-JS/tree/master/es6%20%26%20beyond

Verwandte Themen