Ghidul complet pentru aceasta în JavaScript

În JavaScript, fiecare funcție are o thisreferință creată automat atunci când o declarați.

JavaScript thiseste destul de similar cu o thisreferință în alte limbaje bazate pe clase, cum ar fi Java sau C # (JavaScript este un limbaj bazat pe prototip și nu are concept de „clasă”): indică obiectul care apelează la funcție (acest obiect numit uneori ca context ). Cu toate acestea, înthis JavaScript, referința din interiorul funcțiilor poate fi legată de diferite obiecte, în funcție de locul în care funcția este apelată .

Iată 5 reguli de bază pentru thislegarea în JavaScript:

Regula 1

Când se apelează o funcție în domeniul global, thisreferința este legată implicit de obiectul global ( windowîn browser sau globalîn Node.js). De exemplu:

function foo() { this.a = 2; } foo(); console.log(a); // 2

Notă: Dacă declarați foo()funcția de mai sus în modul strict, atunci apelați această funcție în domeniul global, thisva fi undefinedși atribuirea this.a = 2va arunca o Uncaught TypeErrorexcepție.

Regula 2

Să examinăm exemplul de mai jos:

function foo() { this.a = 2; } const obj = { foo: foo }; obj.foo(); console.log(obj.a); // 2

În mod clar, în fragmentul de mai sus, foo()funcția este apelată cu contextul este objobiect și thisreferința acum este legată obj. Deci, atunci când o funcție este apelată cu un obiect context, thisreferința va fi legată de acest obiect.

Regula 3

.call, .applyși .bindpot fi folosite toate pe site-ul apelului pentru a lega în mod explicit this. Utilizarea .bind(this)este ceva ce puteți vedea în destul de multe componente React.

const foo = function() { console.log(this.bar) } foo.call({ bar: 1 }) // 1

Iată un exemplu rapid despre modul în care fiecare este folosit pentru a lega this:

  • .call(): fn.call(thisObj, fnParam1, fnParam2)
  • .apply(): fn.apply(thisObj, [fnParam1, fnParam2])
  • .bind(): const newFn = fn.bind(thisObj, fnParam1, fnParam2)

Regula 4

function Point2D(x, y) { this.x = x; this.y = y; } const p1 = new Point2D(1, 2); console.log(p1.x); // 1 console.log(p1.y); // 2

Lucrul pe care trebuie să-l observați este Point2Dfuncția numită cu newcuvânt cheie, iar thisreferința este obligată să p1obiecteze. Deci, atunci când o funcție este apelată cu newcuvânt cheie, va crea un obiect nou și thisreferința va fi legată de acest obiect.

Notă: pe măsură ce numiți o funcție cu newcuvânt cheie, o numim și funcție de constructor .

Regula 5

JavaScript determină valoarea de thisla runtime, pe baza contextului curent. Deci, thisuneori, poate indica altceva decât ceea ce vă așteptați.

Luați în considerare acest exemplu de clasă Cat cu o metodă numită makeSound(), urmând modelul din regula 4 (de mai sus) cu o funcție constructor și newcuvântul cheie.

const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.makeSound(); // Fat Daddy says: Mrrooowww

Acum, să încercăm să oferim pisicii o cale către annoy()oameni prin repetarea sunetului său de 100 de ori, o dată la jumătate de secundă.

const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const t = setInterval(function() { this.makeSound(); // <-- this line fails with `this.makeSound is not a function` count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();

Asta nu funcționează, deoarece în setIntervalcallback am creat un nou context cu scop global, deci thisnu mai indică instanța noastră de pisică. Într-un browser web, thisva indica în schimb obiectul Window, care nu are o makeSound()metodă.

Câteva moduri de a-l face să funcționeze:

  1. Înainte de a crea noul context, atribuiți thisunei variabile locale numite mesau selfsau oricum doriți să o numiți și utilizați acea variabilă în interiorul apelului invers.
const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const self = this; const t = setInterval(function() { self.makeSound(); count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();
  1. Cu ES6 puteți evita atribuirea thisunei variabile locale utilizând o funcție săgeată, care se leagă thisde contextul codului înconjurător unde este definit.
const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const t = setInterval(() => { this.makeSound(); count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();