Funkcje ES6, funkcje strzałek i "to" w klasie ES6 [duplikat]
class App extends Component {
constructor(props) {
...
}
onChange = (e) => this.setState({term: e.target.value})
onSubmit(e){
e.preventDefault();
const api_key = "C1hha1quJAQZf2JUlK";
const url = `http://api.giphy.com/v1/gifs/search?q=${this.state.term}&api_key=${api_key}`;
}
render() {
return (
<div>
<form onSubmit={this.onSubmit}>
<input value={this.state.term} onChange={this.onChange}/>
<button>Search!</button>
</form>
</div>
);
}
}
Jaka jest różnica pomiędzy dwoma typami funkcji zadeklarowanymi w klasie (onChange i onSubmit). Dostaję błąd w odniesieniu do tego.sate in const url jeśli I deklaruje ją jako metodę klasy ES6, ale zmiana jej na funkcję arrow ją naprawia.
Chcę wiedzieć, jak dokładnie " to " jest obsługiwane w obu przypadkach
Również, jak zrobić to w drugą stronę? Powiedzmy, że jeśli chcę użyć tej samej funkcji onSubmit (metoda klasy ES6), ale chcę obsłużyć to, gdy ją wywołam (w elemencie formularza), Jak to zrobić ?
używając tego.onSubmit.bind (this)?
5 answers
Ważne jest, aby wiedzieć, że składnia ta:
class A {
method = () => {}
}
Jest tylko cukrem składniowym do tworzenia metody instancji w konstruktorze klasy:
class A {
constructor() {
this.method = () => {}
}
}
Uwaga: Ta składnia nie jest jeszcze oficjalną częścią języka JavaScript (obecnie w etapie 3), więc musisz użyć transpilera podobnego do Babel do obsługi .
Wartość this
wewnątrz method
jest klasą A
, ponieważ na to wskazuje this
w konstruktorze (od strzałka funkcje dziedziczą kontekst z zakresu, w którym są zdefiniowane):
class A {
constructor() {
this.method = () => this;
}
}
const instance = new A();
console.log(instance.method() === instance); // true
Definiowanie zwykłej (Nie-funkcji strzałkowej) metody na klasie tworzy metodę na prototypie klasy (nie instancję), ale nie ustala reguł co this
będzie (ponieważ this
jest dynamiczna w JS i zależy od tego, jak funkcja jest wywoływana, a nie jak jest zdefiniowana ).
class A {
method() {}
}
console.log(new A().method === A.prototype.method); // true
Jeśli metody zdefiniowane w którymkolwiek z tych sposobów są wywoływane na instancji klasy (poprzez .
), zgodnie z regułą jak this
jest związana, gdy funkcja jest wywoływana jako metoda obiektu, this
wskaże instancję klasy w obu przypadkach:
class A {
constructor() {
this.methodOnInstance = () => this;
}
methodOnPrototype() { return this; }
}
const instance = new A();
console.log(
instance.methodOnInstance() === instance.methodOnPrototype(), // true
instance.methodOnPrototype() === instance // true
);
Jedną z głównych różnic między dwiema powyższymi deklaracjami metody jest to, że metoda instancji ma this
zawsze stałe do instancji klasy, podczas gdy metoda class (prototype) nie (możemy ją zmienić za pomocą funkcji .prototyp.zastosuj lub funkcja.prototyp.call )
class A {
constructor() {
this.methodOnInstance = () => this;
}
methodOnPrototype() { return this; }
}
const instance = new A();
console.log(
instance.methodOnInstance() === instance.methodOnPrototype(), // true
instance.methodOnPrototype.call('new this') === 'new this' // true
);
Częstym zjawiskiem, w którym this
zmiany znajdują się wewnątrz procedury obsługi zdarzeń, gdzie procedura obsługi zdarzeń wywołuje przekazaną do niej funkcję i wiąże kontekst z elementem, na którym zdarzenie miało miejsce (tak więc nadpisuje wartość this
jako element, który został kliknięty lub cokolwiek to było zdarzenie)
Dzieje się tak również w Reaccie dla wszystkich (syntetycznych) procedur obsługi zdarzeń DOM.
Dlatego, jeśli aby kontekst naszej metody zawsze wskazywał na instancję komponentu Reactowego, możemy użyć tej metody.
Innym sposobem ograniczenia kontekstu, ale bez użycia specjalnej składni metody instancji, która wymaga Babel, jest bezpośrednie utworzenie metody instancji przez utworzenie nowej funkcji z metody klasy (prototype) z powiązanym kontekstem (za pomocą funkcji .prototyp.bind):
class A {
constructor() {
this.methodOnInstance = this.methodOnPrototype.bind(this);
}
methodOnPrototype() { return this; }
}
const instance = new A();
console.log(
instance.methodOnInstance() === instance.methodOnPrototype(), // true
instance.methodOnPrototype() === instance // true
);
To pozwala nam dotrzeć do tego samego wynik jako użycie składni metody wystąpienia specjalnego, ale z aktualnie dostępnymi narzędziami (ES2017 i under).
Jeśli z jakiegoś powodu chcemy metody, która jest zawsze związana z czymś, co nie jest instancją klasy, możemy to zrobić również: {21]}
class A {
constructor() {
this.method = this.method.bind(console);
}
method() { return this; }
}
const instance = new A();
console.log(
instance.method() === console // true
);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-27 03:11:53
Wyrażenie funkcji strzałki ma krótszą składnię niż funkcja ekspresji i nie ma własnego tego, argumentów, super, czy nowy.cel. Te wyrażenia funkcyjne najlepiej nadają się dla NIE-metody funkcji i nie mogą być używane jako konstruktory.
Funkcje strzałek leksykalnie wiążą swój kontekst, więc w rzeczywistości odnosi się to do kontekstu początkowego.
W deklaracji funkcji ES3/4 można użyć this
przechowując ją w innej zmiennej.
const that = this;
onSubmit(e){
e.preventDefault();
const api_key = "***************";
const url = `http://api.giphy.com/v1/gifs/search?q=${that.state.term}&api_key=${api_key}`;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-22 05:25:34
Jak mam to zrobić w drugą stronę? Powiedzmy, że jeśli chcę użyć tej samej funkcji onSubmit (metoda klasy ES6), ale chcę obsłużyć to, gdy ją wywołam (w elemencie formularza), Jak to zrobić ?Używając tego.onSubmit.bind (to)?
Tak musisz powiązać metodę z komponentem w konstruktorze. Dzieje się tak dlatego, że funkcje strzałek są automatycznie przypisywane do klasy, dlatego zakres tego jest ustawiany w metodzie. While {[0] } Jest funkcją regularną, która nie jest jeszcze związana dlatego to wewnątrz metody będzie odwoływać się do funkcji, a nie do komponentu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55
Musisz użyć bind
w konstruktorze swojej klasy z metodą klasy ES6. Zasadniczo funkcje strzałek robią to za ciebie automatycznie.
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
}
Ważniejsze jest to, że wierzę, że funkcja arrow tutaj zostanie utworzona na każdej instancji klasy, gdzie metoda klasy ES6 będzie częścią prototypu klasy i udostępniona wszystkim instancjom.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-22 05:28:01
Zasadnicza różnica polega na tym, że w ES5 nie mamy automatycznego wiązania, co oznacza, że musisz ręcznie powiązać funkcję obsługi zdarzeń, aby grać z state lub props wewnątrz funkcji w reaccie. Ale w ES6 robi automatyczne wiązanie. To jest kluczowa różnica
ES5: musisz bindować onSubmit najlepiej w konstruktorze
//is valid
this.onSubmit = this.onSubmit.bind(this);
onSubmit(e){
e.preventDefault();
const api_key = "C1hha1quJAQZf2JUlK";
const url = `http://api.giphy.com/v1/gifs/search?q=${this.state.term}&api_key=${api_key}`;
}
ES6:
Poniższy tekst jest ważny, ponieważ powoduje automatyczne wiązanie.
onChange = (e) => this.setState({term: e.target.value})
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-22 05:42:29