Definiując funkcję w języku Javascript możemy też tworzyć klasy obiektów, a dokładniej konstruktory tych klas. Tutaj należy zwrócić szczególną uwagę na zmienną "this" wskazującą na aktualny obiekt klasy, bo zasięg tej zmiennej może być ograniczony lokalną zmienną "this" zwykłej funkcji której definicja znajduje się wewnątrz konstruktora. Problemu tego nie ma z funkcjami strzałkowymi które nie tworzą swoje lokalnego kontekstu (closure) i dlatego zawsze odwołują się do "this" widzianego na zewnątrz, jest to szczególnie użyteczne w momencie kiedy użyjemy całego łańcucha funkcji ze strzałką gdzie wynik jednej funkcji => jest parametrem wejściowym drugiej funkcji strzałkowej.
function BookList (prefix) {
this.prefix = prefix;
this.prefix2 = 'd'
this.makeGetBooksWithPrefix = function() {
return () => {
/* zmienna "this" objektu klasy BookList lub*/
/* zmienna "this" metody getBooksWithPrefix */
return ["book1", "book2", "book3"].map(book => `${this.prefix}${book}` );
}
}
this.getBooksWithPrefix1 = (() => {
return () => {
/* atrybut "this.prefix" objektu klasy BookList, nieokreślony jeszcze w definicji klasy */
return ["book1", "book2", "book3"].map(book => `${this.prefix}${book}` );
}
})();
this.getBooksWithPrefix2 = (() => {
return () => {
/* atrybut "this.prefix2" klasy BookList, określony w definicji klasy */
return ["book1", "book2", "book3"].map(book => `${this.prefix2}${book}` );
}
})();
this.getBooksWithPrefix3 = (function() {
/* funkcja tworzy nowy lokalny "this", war. this.prefix2 będzie undefined */
return () => {
/* zmienna "this" metody getBooksWithPrefix3 */
return ["book1", "book2", "book3"].map(book => `${this.prefix2}${book}` );
}
})();
this.getBooksWithPrefix4 = (function() {
/* lokalne "this" zostaje zastąpione kontekstem objektu BookList dzięki bind(this)*/
return () => {
/* zmienna "this" metody getBooksWithPrefix3 */
return ["book1", "book2", "book3"].map(book => `${this.prefix2}${book}` );
}
}).bind(this)();
}
let c = new BookList('*');
let d = new BookList('x');
/* użycie funkcji wygenerowanej lokalnie w miejscu wywołania: */
console.log( c.makeGetBooksWithPrefix()() );
console.log( d.makeGetBooksWithPrefix()() );
/* użycie funkcji wygenerowanych wcześniej w konstruktorze: */
console.log( d.getBooksWithPrefix1() );
console.log( d.getBooksWithPrefix2() );
console.log( d.getBooksWithPrefix3() );
console.log( d.getBooksWithPrefix4() );
// wynik funkcji stworzonej lokalnie:
// [ '*book1', '*book2', '*book3' ]
// [ 'xbook1', 'xbook2', 'xbook3' ]
// wynik funkcji stworzonych w konstruktorze:
// [ 'xbook1', 'xbook2', 'xbook3' ]
// [ 'dbook1', 'dbook2', 'dbook3' ]
// [ 'undefinedbook1', 'undefinedbook2', 'undefinedbook3' ]
// [ 'dbook1', 'dbook2', 'dbook3' ]
Przykład powyżej pokazuje jak zastosowanie notacji strzałkowej (arrow functions) zmienia znaczenie zmiennej "this". Każde odwołanie do "this" wewnątrz funkcji strzałkowej odnosi się do zasięgu w którym taka funkcja jest definiowana, jeżeli brakuje szukanej zmiennej to sprawdzany jest zasięg bardziej zewnęczny - w przykładzie powyżej this.prefix
nie jest zdefiniowany w funkcji makeGetBooksWithPrefix
więc pobrany jest prefix z funkcji BookList
. Ponieważ funkcja makeGetBooksWithPrefix
tworzy i zwraca właściwą funkcję anonimową w miejscu jej wywołania to właśnie w tym momencie określana jest wartość this.prefix
. (jest to aktualna wartość atrybutu prefix w obiekcie klasy BookList
).
Podobnie zachowuje się anonimowa funkcja przypisana do zmiennej getBooksWithPrefix1
- wartość this.prefix
jest nieokreślona w momencie generowania tej funkcji więc użycie tej funkcji dla konkretnego obiektu pobiera aktualną wartość this.prefix
tego obiektu.
Funkcja przypisana do atrybutu getBooksWithPrefix2
jest dokładnie taką samą anonimową funkcją strzałkową wygenerowaną przez inną anonimową funkcję strzałkową jak getBooksWithPrefix1
ale różnica polega na tym że funkcja ta odwołuje się do atrybutu this.prefix2
który jest dostępny w definicji konstruktora.
Następny przypadek to zwykła funkcja która zwraca funkcję strzałkową i przypisuje ją do atrybutu getBooksWithPrefix3
. Tutaj zwracana funkcja strzałkowa nie ma dostępu ani do this.prefix
ani też do this.prefix2
więc zwrócona będzie wartość "undefined" (zwykła funkcja zdefiniowana za pomocą słowa kluczowego function
tworzy swoją lokalną zmienną this).
I ostatnia funkcja przypisana do pola getBooksWithPrefix4
to dokładna kopia funkcji z pola getBooksWithPrefix3
, jedyna różnica to użycie bind(this)
na funkcji anonimowej function() {...
bezpośrednio przed jej wywołaniem, funkcja bind(this)
przekazuje do funkcji anonimowej kontekst objektu klasy, więc aktualne wartości pól objektu klasy BookList
są ponownie dostępne.
Congratulations @damii! You received a personal award!
Click here to view your Board
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Hello @damii! This is a friendly reminder that you have 3000 Partiko Points unclaimed in your Partiko account!
Partiko is a fast and beautiful mobile app for Steem, and it’s the most popular Steem mobile app out there! Download Partiko using the link below and login using SteemConnect to claim your 3000 Partiko points! You can easily convert them into Steem token!
https://partiko.app/referral/partiko
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Congratulations @damii! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Vote for @Steemitboard as a witness to get one more award and increased upvotes!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit