2016-03-26 24 views
8

Czy ktoś mógłby wyjaśnić, dlaczego zdefiniowanie funkcji prototypowej z wyrażeniem lambda nie działa? Myślałem, że to musi być wcześniej zadane, ale nie mogłem go znaleźć.Dlaczego nie można użyć funkcji lambda do zdefiniowania funkcji prototypowej?

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

to nie działa

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

i to jest w porządku, oczywiście:

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

tłuszczu strzały nie mają" tego " – georg

+0

@georg Myślę, że to robi, ale po prostu nie to, co myślałem, że to było. – stt106

+0

@ stt106: komentarz georg jest poprawny, oprócz tego, że brakuje dwóch słów: "a" i "bindowanie": "strzałki nie mają" wiązania ". "Wiązanie" to mechanizm, którego specyfikacja JavaScript używa do mówienia o rozwiązywaniu takich rzeczy jak "this", nazwy zmiennych i nazwy stałe. Na przykład funkcja deklarująca zmienną o nazwie "a" ma * wiązanie * dla tej zmiennej (pośrednio poprzez rekord env). Normalne funkcje mają * oprawa * dla 'this', która jest ustawiona na wartość, gdy są one wywoływane, ale funkcje strzałki nie, dlatego zamykają się na powiązanie tego kontekstu, w którym zostały utworzone . –

Odpowiedz

11

Jedną z głównych funkcji funkcji strzałkowych jest to, że zamykają ponad z this z kontekstu, w którym zostały utworzone; nie dostają tego na podstawie tego, jak nazywają się tak, jak robią to inne funkcje. Więc ...

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

Ale twoja funkcja polega na this jest różny w zależności od tego, jak to się nazywa.

To nie jest przypadek użycia funkcji strzałek. Użyć zwykłej funkcji:

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

albo jeszcze lepiej, korzystać z nowego class składnię:

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

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

Arrow function rozwiąże kontekst this należy do zakresu, w którym funkcja została zdefiniowana. Wydaje mi się, że zdefiniowałeś tę funkcję w zakresie window. Tak więc this wskaże w swojej funkcji window.

Możesz użyć normalnego tutaj. I musimy być ostrożni podczas używania funkcji strzałek.

+0

dzięki i to ma teraz sens; ale przyjmuję inną odpowiedź, ponieważ zapewnia ona nieco więcej wglądu; mam nadzieję, że nie miałbyś nic przeciwko. – stt106

+0

@ stt106 Możesz to zrobić. Chętnie pomogę przy okazji :) –

0

Oprócz @t-j-crowder „s answer chciałem zostawić przypadek testowy (mokka wymuszenia), który cię może wykorzystać do wizualizacji, które nie działa.

Ponadto można przeczytać więcej na temat zakresu funkcji strzałek tutaj: You Don't Know JS Kyle Simpsona, który wyjaśnia this w szczegółach.

Zasadniczo funkcja strzałki this wskazuje na otaczający kontekst bieżącego kontekstu, który przydaje się, jeśli posiadasz funkcje otaczające. Co to jest w zasadzie robi rzeczy var self = this;.

Albo jak Kyle mówi:

[...] leksykalna this w funkcji wywołania zwrotnego strzałka w poprzednim fragmencie wskazuje teraz na taką samą wartość jak w otaczającej makeRequest(..) funkcji. Innymi słowy, => jest syntaktycznym stand-inem dla var self = this.

W przypadku, gdy var self = this (lub alternatywnie, wywołanie funkcji .bind(this)) byłoby zwykle pomocne, funkcje strzałek są ładniejszą alternatywą działającą na tej samej zasadzie. [...]

można go przetestować się z moim GIST: https://gist.github.com/jay-bricksoft/96738dd8a48ceb9f517e914b834cc1ee

w moim przypadku testu było to wyjście:

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: dodano example/odniesienie do Kyle Simpson „You Don 't Know ES6 " https://github.com/getify/You-Dont-Know-JS/tree/master/es6%20%26%20beyond

Powiązane problemy