Funkcije strelica i ključna riječ this u JavaScriptu

Zadnje ažuriranje: 02/10/2026
  • Funkcije strelica pružaju konciznu sintaksu i snimanje this leksički iz svog okolnog opsega, umjesto stvaranja vlastitog povezivanja.
  • Vrijednost this u regularnim funkcijama ovisi o tome kako se pozivaju, što utječe na funkcije, metode, konstruktore, klase i povratne pozive.
  • Funkcije strelica idealne su za povratne pozive i metode nizova, ali su loš izbor za metode objekata, rukovatelje DOM događajima i konstruktore.
  • Razumijevanje kada this Dinamičko naspram leksičkog je bitno kako bi se izbjegle suptilne greške i kako bi se moglo birati između funkcija strelica i tradicionalnih funkcija.

Funkcije strelica i ovo u JavaScriptu

Ako ste se ikada prijavili this u različitim JavaScript funkcijama i dobili izrazito različite rezultate, niste sami. Mnogi programeri nailaze na slučajeve u kojima metoda ispisuje očekivani objekt, a funkcija strelice ispisuje window, a ugniježđena strelica odjednom „čarobno“ pokazuje natrag na okolni objekt. Razumijevanje zašto se to događa ključno je za pisanje predvidljivog koda bez grešaka.

Funkcije strelica i this Ključna riječ čini jednu od najvažnijih (i pogrešno shvaćenih) kombinacija u modernom JavaScriptu. Funkcije strelica izgledaju kao samo kraća sintaksa, ali ispod haube mijenjaju način this se obrađuje, kako se ponašaju povratni pozivi, pa čak i kada ih trebate ili ne trebate koristiti kao metode. Prođimo kroz sve korak po korak, od sintakse do konteksta izvršavanja, koristeći jednostavan jezik i mnogo praktičnih primjera.

Sintaksa funkcije strelice bez zbrke

Funkcije strelica su izrazi funkcija napisani s => sintaksa umjesto function ključne riječi. Konceptualno, možete ih smatrati sažetim načinom pisanja: „uzmi ove parametre, procijeni ovaj izraz ili blok koda i vrati vrijednost.“ U osnovi su i dalje funkcije, ali se ponašaju drugačije na nekoliko važnih načina.

Najosnovnija funkcija strelice izravno se preslikava u izraz regularne funkcije. Na primjer, ovaj klasični izraz funkcije:

const multiplyByTwo = function (value) { return value * 2; };

Može se prepisati kao funkcija strelice ovako:

const multiplyByTwo = (value) => { return value * 2; };

Funkcije strelica su dobre kada je tijelo jedan izraz. Ako je tijelo samo jedna naredba koja vraća nešto, možete izostaviti i vitičaste zagrade i eksplicitnu naredbu return, što omogućuje implicitni povratak:

const multiplyByTwo = value => value * 2;

Kada postoji točno jedan parametar, možete izostaviti okolne zagrade, ali samo u tom specifičnom slučaju. So x => x * 2 je valjan, ali ako imate nula ili više parametara, morate zadržati zagrade:

  • Nulti parametri: () => 42
  • Jedan parametar: x => x * 2 or (x) => x * 2
  • Dva ili više parametara: (x, y) => x + y

Kada vam je potrebno više od jedne naredbe u tijelu, morate koristiti vitičaste zagrade i eksplicitnu return. U toj situaciji, funkcije strelica ponašaju se kao regularne funkcije u pogledu povrata: ne return, nije vraćena nikakva vrijednost.

const feedCat = (status) => {
if (status === 'hungry') {
return 'Feed the cat';
} else {
return 'Do not feed the cat';
}
};

Budite oprezni pri vraćanju literala objekta iz funkcija strelica, jer se zagrade objekta mogu zamijeniti s tijelom funkcije. Kako biste izbjegli tu dvosmislenost, stavite literal objekta u zagrade kako bi JavaScript znao da je to izraz koji treba vratiti:

const toObject = value => ({ result: value });

Još jedna stvar: funkcije strelica su uvijek izrazi, nikada deklaracije. To znači da se moraju dodijeliti varijabli, svojstvu ili proslijediti kao argument; ne mogu stajati samostalno kao function myFunc() {}, i ne podižu se na isti način kao deklaracije funkcija, pa ih ne možete pozvati prije nego što su definirane.

Što je točno this u JavaScriptu?

Ključna riječ this je dinamičko povezivanje koje JavaScript stvara za vas kada izvršava funkciju ili metodu klase. Možete ga smatrati nevidljivim parametrom čija vrijednost ovisi o tome kako i gdje se funkcija poziva. To ga čini moćnim i fleksibilnim, ali i velikim izvorom zbrke.

U nestrogoj funkciji, this uvijek se rješava kao neka vrsta objekta; u strogom načinu rada može biti doslovno bilo koja vrijednost, uključujući undefined. JavaScript odlučuje o toj vrijednosti na temelju konteksta izvršavanja: regularna funkcija, poziv metode, poziv konstruktora, klasa, globalni opseg ili funkcija strelice.

Na najvišoj razini klasičnog skripta (ne modula), this odnosi se na globalThis, što je obično adresa preglednika window objekt. Dakle, sljedeća usporedba u pregledniku bit će istinita:

console.log(this === window); // true

U funkcijama koje nisu strelice, this u potpunosti je određeno mjestom poziva. Ako pozoveš obj.method(), zatim unutra method vrijednost this is objAko uzmete istu tu funkciju i nazovete je samostalnom kao fn() u strogom načinu rada, this postaje undefined; u nestrogom načinu rada, JavaScript "zamjenjuje" this sa globalThis.

Važno je napomenuti da nije važno gdje je funkcija definirana, već kako se poziva. Metoda može postojati u lancu prototipova ili biti dodijeljena drugom objektu i dalje vidjeti this kao bilo koji objekt koji se zapravo koristi u vrijeme poziva. Prosljeđivanje metode često mijenja njezin this osim ako to izričito ne popravite.

Postoje i alati za kontrolu this eksplicitno: call, apply, bindi Reflect.apply. To vam omogućuje da "ubrizgate" željeno this vrijednost: fn.call(obj, arg1, arg2) izvršit će fn sa this postavljen na objIsta pravila zamjene primjenjuju se i u nestrogom načinu rada: ako prođete null or undefined as this, zamjenjuju se s globalThis; primitivi se uokviruju u svoje omotačke objekte.

Povratni pozivi dodaju još jedan sloj indirekcije, jer this kontrolira onaj tko zove vaš povratni poziv. Metode iteracije niza, Promise konstruktor i slični API-ji obično pozivaju povratne pozive s this postavljen na undefined (ili globalni objekt u nemarnom načinu rada). Neki API-ji, poput Array.prototype.forEach or Set.prototype.forEach, prihvatite zasebno thisArg parametar koji možete koristiti za postavljanje povratnog poziva this.

Drugi API-ji namjerno pozivaju povratne pozive s prilagođenim this vrijednosti. Na primjer, reviver argument za JSON.parse i replacer za JSON.stringify dobiti this vezano za objekt koji posjeduje svojstvo koje se trenutno obrađuje. Obrađivači događaja u DOM-u vezani su za element kojem su pridruženi kada su napisani na "klasičan" način.

Osnovna ideja: funkcije strelica ne stvaraju vlastite this

Odlika funkcija strelica je da nikada ne stvaraju novi this obvezujući. Umjesto toga, oni se zatvaraju (ili "hvataju") this iz okolnog leksičkog okruženja u trenutku njihovog stvaranja. Kada se strelica kasnije izvrši, ona jednostavno ponovno koristi tu snimljenu vrijednost, bez obzira na to kako je nazovete.

U praksi, funkcija strelice ponaša se kao da je trajno automatski vezana za this njegovog vanjskog opsega. Zato su metode poput call, applyi bind ne mogu se promijeniti this za funkciju strelice: thisArg argument se jednostavno ignorira. I dalje im možete proslijediti regularne parametre, ali this vrijednost je zaključana.

Razmotrite ovaj isječak u globalnom opsegu skriptne datoteke:

const arrow = () => console.log(this);
arrow();

Budući da je strelica definirana u globalnom kodu, njezina this je globalno this (tipično window u skripti preglednika) i to se nikada ne mijenja. zvanje arrow kao obična funkcija, dodjeljivanjem svojstvu ili prosljeđivanjem uvijek će se zabilježiti isti globalni objekt kada se pozove u ovom kontekstu.

Zaista zanimljivo ponašanje se javlja kada ugnijezdite funkcije strelica unutar regularnih funkcija ili metoda. Budući da strelica obuhvaća vanjsku funkciju this, postaje moćan alat za povratne pozive koji se trebaju pozivati ​​na objekt koji ih sadrži bez uobičajenog .bind(this) ceremonija.

const counter = {
id: 42,
start() {
setTimeout(() => {
console.log(this.id); // uses counter.id
}, 1000);
},
};

If start koristili smo tradicionalnu anonimnu funkciju unutra setTimeout, morali biste ručno vezati this ili ga spremiti u varijablu. Sa strelicama, povratni poziv prirodno nasljeđuje this iz start, Što je counter, Tako da this.id ispisi 42 kako je predviđeno.

Ovo leksičko vezivanje također objašnjava klasično „zašto this "promjena" pitanje pri korištenju strelica u literalima objekta. Pogledajte ova dva objekta:

const obj1 = {
speak() {
console.log(this);
}
};

const obj2 = {
speak: () => {
console.log(this);
}
};

zvanje obj1.speak() ispisi obj1, Jer je speak je uobičajena metoda i this postavlja se na temelju mjesta poziva. Po kontrastu, obj2.speak() zapisi vanjskog this (često window u preglednicima), jer strelica ne koristi objekt kao svoj thisSam literal objekta ne stvara novi this opseg; samo tijelo funkcije to radi, a funkcije strelica preskaču taj korak.

Sada razmotrimo metodu objekta koja stvara i odmah poziva unutarnju strelicu:

const obj3 = {
speak() {
(() => {
console.log(this);
})();
}
};

obj3.speak();

U ovoj situaciji, funkcija unutarnje strelice nasljeđuje this iz speak, Što je obj3 kada se naziva obj3.speak(). Iako je strelica ugniježđena, odmah pozvana funkcija, ona i dalje pokazuje na obj3, a ne globalni objekt. To je bit leksičkog this: prati okolni opseg, a ne mjesto poziva same strelice.

this između funkcija, objekata i konstruktora

Da biste stvarno savladali funkcije strelica i this, pomaže vidjeti kako this radi u svakom glavnom kontekstu: regularnim funkcijama, metodama, konstruktorima, klasama i globalnom opsegu. Nakon što su ta pravila jasna, ponašanje strelice je puno lakše objasniti.

U običnoj funkciji (bez strelice), this ovisi 100% o tome kako se funkcija poziva. Ako pozoveš fn() u strogom načinu rada, this is undefined; u nemarnom načinu rada, zamjena čini this postati globalThisAko nazoveš obj.fn(), A zatim this is objPomakni se fn na drugi objekt ili na varijablu i vrijednost this kretat će se u skladu s tim.

U metodi definiranoj na literalu objekta, this je objekt na kojem se pristupa metodi, ne nužno onaj na kojem je metoda izvorno definirana. If obj.__proto__ sadrži metodu i pozivate je obj.method(), zatim unutra method, this is obj, a ne prototip.

Konstruktori su još jedan poseban slučaj: kada pozovete funkciju s new, this vezan je za novokreiranu instancu objekta. Na primjer, u function User(name) { this.name = name; }, zovem new User('Alex') setovi this na novo User objekt. Ako konstruktor eksplicitno vrati neprimitivni objekt, taj vraćeni objekt zamjenjuje this kao konačna vrijednost new izraz.

Sintaksa klase temelji se na ovim pravilima s dva glavna konteksta: instančnim i statičkim. Unutar konstruktora ili metode instance, this pokazuje na instancu klase s kojom radite. Unutar statičkih metoda ili statičkih inicijalizacijskih blokova, this odnosi se na samu klasu (ili izvedenu klasu kada se poziva putem nasljeđivanja). Polja instance se procjenjuju s this vezano za novu instancu; statička polja vidi this kao konstruktor klase.

Konstruktori izvedenih klasa ponašaju se malo drugačije: sve dok ne pozovete super(), nema upotrebljivog this. Pozivanje super() inicijalizira this delegiranjem osnovnom konstruktoru; vraćanje prije toga u izvedenom konstruktoru dopušteno je samo ako eksplicitno vratite drugi objekt.

U globalnom kontekstu, this ovisi o tome kako JavaScript okruženje omotava i izvršava vaš kod. U klasičnom skriptu preglednika, najviše razine this je globalni objekt; u ES modulu, najviša razina this je uvijek undefinedNode.js CommonJS moduli su interno omotani i obično se izvršavaju s this postavljen na module.exportsAtributi inline rukovatelja događajima u HTML-u izvršavaju se s this postavljeni na element kojem su pridruženi.

Jedan suptilan, ali važan detalj: sami literali objekata ne uvode novi this opseg. pisanje const obj = { value: this }; unutar skripte će napraviti obj.value jednak vanjskom this, a ne objekt. Samo tijela funkcija (i tijela klasa) stvaraju namjenski this vezanje; strelice namjerno preskaču ovaj korak i nasljeđuju.

Zašto su funkcije strelica izvrsne za povratne pozive (a kada nisu)

Jer se funkcije strelica zatvaraju this, savršeno se uklapaju u mnoge scenarije povratnog poziva gdje želite da povratni poziv nastavi upućivati ​​na okolni objekt ili kontekst. Ovo je posebno korisno s timerima, obećanjima i metodama nizova poput map, filteri reduce.

Zamislite metodu koja treba više puta ažurirati neko svojstvo koristeći setInterval. Koristeći tradicionalnu funkciju, this unutar povratnog poziva bi se prema zadanim postavkama prebacio na globalni objekt (ili bi bio undefined u strogom načinu rada), dakle this.count ne bi pokazivao na vašu instancu. Kod funkcije strelice, povratni poziv prirodno koristi this vanjske metode.

function Counter() {
this.count = 0;

setInterval(() => {
this.count++;
}, 1000);
}

Zahvaljujući strijelu, this unutar intervala povratni poziv odnosi se na Counter primjer, ne window. Da je taj povratni poziv regularna funkcija, trebali biste ili .bind(this) ili međuvarijabla poput const self = this; zadržati referencu.

Funkcije strelica također pojednostavljuju kod korištenjem metoda polja, gdje vas često nije briga this uopće. Kada prosljeđujete tradicionalnu funkciju kao povratni poziv, implicitni this je obično undefined, a to biste mogli zaboraviti. Strelice vizualno pokazuju da je funkcija samo čisto preslikavanje ulaza u izlaze.

const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);

Međutim, postoje važni slučajevi u kojima su funkcije strelica pogrešan izbor, posebno kada vam je potrebna dinamička this. Dva klasična anti-uzorka koriste funkcije strelica kao metode objekta i kao rukovatelje DOM događajima koji se oslanjaju na this biti element.

Razmotrimo objekt koji prati živote mačke:

const cat = {
lives: 9,
jump: () => {
this.lives--; // bug: this is not cat
},
};

cat.jump();

Od jump je strelica, this ne odnosi se na cat ali što god this gdje je kreiran literal objekta (često globalni objekt). Namjera this.lives-- ili baca (u strogom načinu rada) ili tiho mutira nešto nepovezano. Korištenje regularne sintakse metode ovdje je ispravan potez.

Slušači DOM događaja su slični: standardni obrazac this.classList.toggle('on') unutar događaja povratni poziv se oslanja na this biti element koji je pokrenuo događaj. S funkcijom strelice, this više ne pokazuje na element, pa se kod prekida.

const button = document.getElementById('press');

button.addEventListener('click', () => {
this.classList.toggle('on'); // this is not button
});

U ovoj situaciji, rukovatelj bi trebao biti normalna funkcija tako da this preglednik ga veže za element gumba. Funkcije strelica jednostavno ne funkcioniraju kao zamjene ako vaša logika očekuje this biti cilj dinamičkog događaja.

Još jedan suptilan nedostatak je taj što su funkcije strelica sintaktički anonimne. Obično nemaju vlastito ime (osim bilo koje varijable kojoj su dodijeljeni), što tragove stoga može učiniti malo manje deskriptivnima, a rekurziju malo težom. U većini koda u stvarnom svijetu to je prihvatljiv kompromis, ali vrijedi ga zapamtiti.

Posebni slučajevi: getteri, seteri, vezane metode i neparni kutovi

Geteri i seteri slijede isto pravilo "poziva stranice": this je objekt na kojem se pristupa svojstvu, a ne onaj na kojem je izvorno definirano. Ako je getter naslijeđen od prototipa i pozovete ga na izvedenom objektu, this unutar gettera se odnosi na izvedeni objekt.

Vezane metode stvorene s Function.prototype.bind daju vam ponašanje donekle slično funkcijama strelica, ali na razini normalnih funkcija. Kad nazovete f.bind(obj), stvarate novu funkciju čija this trajno je fiksiran na obj, bez obzira na to kako se poziva. To može biti korisno u razredima kada trebate sačuvati this čak i ako je metoda odvojena.

class Example {
constructor() {
this.handleClick = this.handleClick.bind(this);
}

handleClick() {
console.log(this); // always the instance
}
}

Nedostatak i vezanih metoda i funkcija strelica koje se koriste kao polja instance je taj što svaka instanca dobiva vlastitu kopiju funkcije, što može povećati korištenje memorije. Ovaj kompromis je obično prihvatljiv kada vežete samo mali broj često odvojenih metoda, ali to je nešto čega treba biti svjestan u kodu koji je kritičan za performanse.

Postoje i neki naslijeđeni kutni slučajevi gdje this ponaša se drugačije, na primjer unutar zastarjelog with izjava. Unutar a with (obj) { ... } blok, pozivanje funkcije koja je svojstvo od obj učinkovito se ponaša kao da ste napisali obj.method(), Tako da this je dužan objModerni kod treba izbjegavati with, ali razumijevanje ove iznimke pojašnjava da this i dalje u osnovi ovisi o tome kako je poziv funkcije formiran.

Ugrađeni rukovatelji događajima u HTML-u također imaju posebno pravilo: okolni ugrađeni kod rukovatelja vidi this kao element, ali unutarnje funkcije definirane unutar tog rukovatelja vraćaju se na regularni this Pravila. Dakle, unutarnja tradicionalna funkcija, koja nije vezana ni za što, obično će vidjeti this as globalThis (Ili undefined u strogom načinu rada), a ne element.

Konačno, zapamtite da funkcije strelica nemaju prototype svojstvo i ne mogu se koristiti kao konstruktori s new. Pokušaj new MyArrow() izbacit će TypeError. Ako vam je potrebna funkcija koja može djelovati kao konstruktor, morate koristiti regularnu funkciju ili klasu.

Imajući na umu ove detalje, mnogo je lakše birati između funkcija strelica i tradicionalnih funkcija. Koristite strelice tamo gdje želite leksički this i konciznu sintaksu te se vraćate na regularne funkcije kad god vam je potrebna dinamična, vođena web-lokacijom poziva this ponašanje ili semantika konstruktora.

Nakon što internalizirate kako this je vezana u svakoj situaciji, funkcije strelica postaju moćan saveznik umjesto iznenađujućeg izvora grešaka. Pojednostavljuju uobičajene obrasce poput povratnih poziva i jednostavnih transformacija, dok regularne funkcije nastavljaju obrađivati ​​uloge koje ovise o njima samima. this povezivanje, kao što su metode, konstruktori i dinamički rukovatelji događajima.

Povezani postovi: