webroad.online
  1. 1Web
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Unelte
  8. 8React
  9. 9State management
  10. 10Next.js
  11. 11Formulare
  12. 12Date și backend
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Animații
  16. 16Testare
  17. 17Arhitectură
JavaScript · Lecția 4 din 17

Scope, hoisting și this

Unde trăiesc variabilele și de ce își „pierde” o metodă this-ul.

Actualizat

Ce este scope

Scope = zona din cod în care o variabilă există și poate fi folosită. În afara ei, variabila nu există.

function order() {
  const total = 100      // există doar în order()
}
console.log(total)       // ✗ ReferenceError

De ce există: fără scope, toate variabilele ar fi globale și s-ar călca pe picioare (două funcții cu un i fiecare).

Tipurile de scope

Tip Creat de Conține
global fișierul / pagina tot ce declari în afara funcțiilor (în module ES — global doar pentru acel modul)
funcție fiecare funcție parametrii și variabilele din ea (inclusiv var)
bloc orice { }: if, for, while, {} simplu let, const, class
const app = 'learn'            // global (al modulului)

function render() {
  const title = 'Funcții'      // scope de funcție
  if (title) {
    const upper = title.toUpperCase()   // scope de bloc
  }
  upper                        // ✗ nu mai există
}

Lexical scope și scope chain

Când folosești o variabilă, JS o caută în scope-ul curent, apoi în scope-ul părinte, apoi în părintele lui… până la global. Acest lanț se numește scope chain.

Important: părintele e decis de locul unde e scrisă funcția în cod (lexical), nu de unde e apelată.

const x = 'global'

function outer() {
  const x = 'outer'
  return function inner() { return x }   // inner e scrisă în outer → vede x-ul lui outer
}

outer()()   // 'outer'

De aici vine closure — vezi Funcții.

Ce este hoisting

Hoisting („ridicare”) = înainte să ruleze codul, JS parcurge scope-ul și înregistrează toate declarațiile. Efectul: unele lucruri pot fi folosite înainte de linia unde sunt scrise.

Fiecare tip de declarație e ridicat diferit:

Declarație Ridicată? Ce găsești dacă o folosești înainte de linia ei
function f() {} da, cu tot cu corp funcția merge normal
var x = 1 da, dar fără valoare undefined
let / const da, dar blocată ReferenceError (TDZ)
class A {} da, dar blocată ReferenceError
const f = () => {} ca orice const ReferenceError
sayHi()                  // ✓ 'Salut' — declarația de funcție e ridicată complet
function sayHi() { return 'Salut' }

console.log(a)           // undefined — var e ridicat, valoarea vine abia la linia lui
var a = 1

console.log(b)           // ✗ ReferenceError
const b = 2

TDZ — temporal dead zone

Între începutul scope-ului și linia unde e declarat un let/const, variabila e într-o „zonă moartă” (TDZ): JS știe că există, dar refuză să te lase s-o folosești. E un lucru bun — prinde bug-uri pe care var le ascundea cu undefined.

Ce înseamnă practic: poți organiza un fișier cu funcția principală sus și helper-ele (declarații function) jos — merge datorită hoisting-ului.

Ce este this

this e o variabilă specială, disponibilă în funcții, care indică obiectul în contextul căruia rulează funcția. Spre deosebire de restul variabilelor, valoarea lui this nu depinde de unde e scrisă funcția, ci de cum e apelată.

Regulile, în ordinea priorității

Cum apelezi this este Exemplu
new Fn() obiectul nou creat new User('Ana')
fn.call(obj), fn.apply(obj), fn.bind(obj) obj, setat explicit greet.call(user)
obj.method() obiectul din fața punctului user.greet()
fn() simplu undefined (în module / strict mode) const g = user.greet; g()
arrow function this-ul din locul unde a fost scrisă — nu are propriul this () => this.name
const user = {
  name: 'Ana',
  greet() { return `Salut, ${this.name}` },
}

user.greet()             // 'Salut, Ana' — this = user

const greet = user.greet
greet()                  // ✗ this e undefined — metoda a fost „desprinsă” de obiect

const bound = user.greet.bind(user)
bound()                  // ✓ 'Salut, Ana'

De ce arrow functions „repară” callback-urile

const timer = {
  seconds: 0,
  start() {
    setInterval(function () { this.seconds++ }, 1000)  // ✗ this nu e timer
    setInterval(() => { this.seconds++ }, 1000)        // ✓ arrow ia this din start()
  },
}

Când îți pasă de this în practică

  • În React modern (funcții + hooks) aproape niciodată.
  • În clase (erori custom, SDK-uri), în event listeners clasici și în cod mai vechi.
  • Regula: metode → funcții normale; callback-uri în interiorul lor → arrow; pasezi o metodă ca callback → bind sau () => obj.method().

Pe scurt

  • Scope = unde trăiește o variabilă: global, funcție, bloc. Căutarea urcă pe scope chain, după locul unde e scris codul.
  • Hoisting = declarațiile sunt înregistrate înainte de rulare; funcțiile merg înainte de definire, let/const dau eroare (TDZ).
  • this depinde de cum apelezi funcția; arrow functions nu au propriul this.

Surse oficiale

Exerciții

Ți-a fost utilă pagina?

Un click — fără cont.