Што такое this? У які момант ствараецца? Ад чаго залежыць кантэкст? Як яго згубіць, чаму губляецца this і як яго знайсці зноў.
this - кантэкст выконвання функцыі. Іншымі словамі - гэта аб'ект, які дадаецца дынамічна ў момант выкліка функцыі і адлюстроўвае той аб'ект, які выклікаў гэтую функцыю. То бок мы можам выклікаць нашу функцыю з рознымі аб'ектамі, і кантэкст будзе змяняцца ў залежнасці ад таго, з якім аб'ектам выкліканая функцыя.
Спосабы выклікання функцыі:
- Звычайны выклік функцыі
- Функцыя, як метад аб'екта
- Як callback для метадаў масіва (
filter,mapі іншых) - Стрэлачная функцыя
- З дапамогай
call,apply,bind - Як канструктар
1. Звычайны выклік
Адказ залежыць ад "use strict". Калі ён уключаны, this для глабальнай вобласці будзе undefined. Калі ражым не строгі, this = window.
text1function printThis() { 2 console.log(this); 3}
2. Функцыя, як метад аб'екта
text1// Маем 2 аб'екта - user і admin і функцыю showRole. 2const user = { 3 role: 'user', 4}; 5 6const admin = { 7 role: 'admin', 8}; 9 10function showRole() { 11 console.log(this.role); 12} 13 14// Дадаем у аб'екты метады showRole 15user.showRole = showRole; 16admin.showRole = showRole; 17 18user.showRole(); // user 19 20admin.showRole(); // admin
Як зразумець, з якім кантэкстам будзе выкліканая функцыя? Трэба паглядзець, што знаходзіцца перад кропкай у момант выкліку функцыі. Гэта і будзе кантэкст.
3. Як callback для метадаў масіва (filter, map і іншых)
cb у метадаў масіву, такіх як map, filter, forEach і іншых, губляе кантэкст, як і ў многіх іншых выпадках ( разглядзім пазней). Калі патрэбна перадаць для cb кантэкст, то ёсць 2 магчымасці для гэтага:
- Метады масіва акрамя cb прымаюць другі неабавязковы аргумент - кантэкст
text1[1, 2, 3].map(cb, this);
- Можна скарыстацца
bind
text1[1, 2, 3].map(cb.bind(this));
4. Стрэлачная функцыя
У arrow funtion свайго this няма. Ён возьмецца са знешняга асяроддзя. Тут падрабязней.
5. З дапамогай call, apply, bind
call і apply дазваляюць адразу выклікаць функцыю з патрэбным кантэкстам. Для call можна дадаткова перадаць аргументы праз коску, для apply - масіў аргументаў.
bind прывязвае кантэкст да функцыі (змяніць ужо нельга), якую можна выклікаць пазней. Тут можна разгледзець падрабязей.
6. Як канструктар
Для канструктара пры выкліку з new ствараецца новы аб'ект, ён прысвойваецца this, дадаюцца ўласцівасці і метады з канструктара, калі няма return (а звычайна мы яго не пішам), з функцыі-канструктара вяртаецца this з захованымі ўласцівасцямі. Тут можна разгледзець падрабязей.
Калі можна згубіць this?
Калі каротка - то любая аперацыя з метадам аб'екта, акрамя яго непасрэднага выкліка, прыводзіць да страты кантэксту.
Вось так добра:
text1let user = { 2 name: "Хведар", 3 hi: function() { console.log('Вітаначкі, ', this.name); }, 4 bye: function() { console.log("Да сустрэчы, ", this.name); } 5}; 6 7user.hi(); 8user.by();
Вось так - не (губляем this):
Thisмае дынамічную вобласць бачнасці, таму кантэкст возьмецца з места выкліка
text1let user = { 2 name: "Хведар", 3 hi: function() { console.log('Вітаначкі, ', this.name); }, 4 bye: function() { console.log("Да сустрэчы, ", this.name); } 5}; 6 7// 1 8const hi = user.hi; 9hi(); // няма аб'екта перад кропкай - кантэкст згубілі. Ён возьмецца з глабальнай вобласці бачнасці. 10 11// 2 12(user.name === "Хведар" ? user.hi : user.bye)(); 13// у нас атрымліваецца (function)() - спачатку выбралі функцыю, а потым толькі выклікалі. 14// І зноў няма аб'екта перад кропкай. 15 16// 3 17 18setTimeout(user.hi, 100);
Спіс можна працягваць і далей, але, думаю, што прынцып зразумелы.
Чаму адбываецца страта this?
Калі мы выклікаем функцыю як метад - user.hi() - JavaScript стварае спецыяльны ўнутраны аб'ект Reference Type. Мы да яго доступа не маем. Ён патрэбны, каб перадаць інфармацыю ад кропкі. да выклікаючых функцыю дужак (). З гэтага аб'екта JavaScript і возьме кантэкст.
Reference Type мае 3 уласцівасці:
base- сам аб'ектname- імя ўласцівасці аб'ектаstrict- ражым выконвання. Калі ўключаны строгі ражым, мае значэннеtrue
Пры любой іншай аперацыі, акрамя непасрэднага выкліка функцыі як метада, Reference Type губляецца (замяняецца на саму функцыю user.hi). Таму звярнуцца да нашага аб'екта мы ўжо не зможам.
Што рабіць:
- Перш за ўсё памятаць пра асаблівасць
thisу JavaScript. - Для
setTimeoutможна выкарыстоўваць функцыі-абгорткі
text1setTimeout(() => user.sayHi(), 1000);
Але трэба улічваць, што за час таймера user можа змяніцца і мы ўбачым зусім не тое, на што разлічвалі.
3.Выкарыстоўваць bind, call, apply
Каментары
(Каб даслаць каментар залагуйцеся ў свой уліковы запіс)