Domů O mně Služby Portfolio Učím Blog Kontakt
← Zpět na učím

05.4 This keyword

Výuka

Proč this?

this keyword je speciální klíčové slovo, které odkazuje na kontext, ve kterém je funkce volána. V objektech odkazuje na sám objekt.

Proč to potřebujeme?

  • Přístup k vlastnostem - Metody můžou číst a měnit vlastnosti objektu
  • Kontext volání - this závisí na tom, KDE a JAK je funkce volána
  • OOP princip - Objekty potřebují odkaz samy na sebe
  • Dynamický this - Stejná funkce může mít různý kontext

Představ si to jako: Zájmeno „já" v konverzaci. Když Alice řekne „já mám 25 let", „já" odkazuje na Alici. Když Bob řekne „já mám 30 let", „já" odkazuje na Boba. this funguje podobně - odkazuje na aktuální kontext.

Jak to funguje?

This keyword:
1. V metodě objektu: this = objekt
2. V normální funkci: this = global object (window/global) nebo undefined (strict mode)
3. Arrow funkce: this = lexikální (z okolního scope)
4. Event handler: this = element, který event vyvolal
5. call/apply/bind: this = explicitně nastavený objekt

Klíčové koncepty

  • this keyword - odkaz na kontext volání
  • Metoda objektu - this = objekt
  • Arrow funkce - this = lexikální (z okolí)
  • Ztráta this - když metodu předáš jako callback
  • bind, call, apply - explicitní nastavení this
  • Strict mode - this je undefined místo global object

JavaScript

Příklad 1: this v metodě objektu

const person = {
  name: 'Alice',
  age: 25,

  greet() {
    console.log(`Hi, I'm ${this.name}`);
    console.log('this:', this);
  }
};

person.greet();
// → Hi, I'm Alice
// → this: { name: 'Alice', age: 25, greet: [Function: greet] }

// this uvnitř metody = objekt person

Co se stalo?

  • this uvnitř metody = objekt, ze kterého byla metoda volána
  • this.name = person.name
  • this odkazuje na celý objekt person

Příklad 2: this v normální funkci (POZOR!)

function showThis() {
  console.log('this:', this);
}

// Normální volání funkce
showThis();
// → this: [object global] (Node.js) nebo Window (prohlížeč)

// Strict mode
'use strict';
function showThisStrict() {
  console.log('this:', this);
}

showThisStrict();
// → this: undefined

// MIMO metodu objektu je this global object nebo undefined

Co se stalo?

  • Normální funkce (ne metoda objektu) má this = global object
  • V strict mode je this = undefined
  • NEBEZPEČNÉ - lepší použít arrow funkci nebo explicit parametr

Příklad 3: Ztráta this (lost this context)

const person = {
  name: 'Bob',

  greet() {
    console.log(`Hi, I'm ${this.name}`);
  }
};

// Přímé volání - OK
person.greet();
// → Hi, I'm Bob

// Uložení metody do proměnné - ZTRÁTA THIS!
const greetFn = person.greet;
greetFn();
// → Hi, I'm undefined (this je global object, ne person)

// Callback - ZTRÁTA THIS!
setTimeout(person.greet, 1000);
// → Hi, I'm undefined (po 1 sekundě)

Co se stalo?

  • Přímé volání: person.greet()this = person
  • Ztráta kontextu: greetFn()this = global object (nebo undefined)
  • Callback: setTimeout(person.greet, ...)this ztracen
  • POZOR: Když metodu předáš jako callback, ztratíš this!

Příklad 4: Řešení ztráty this - arrow funkce a bind

const person = {
  name: 'Charlie',

  greet() {
    console.log(`Hi, I'm ${this.name}`);
  }
};

// ❌ Problém - ztráta this
setTimeout(person.greet, 1000);
// → Hi, I'm undefined

// ✅ Řešení 1: Arrow funkce wrapper
setTimeout(() => {
  person.greet();
}, 1000);
// → Hi, I'm Charlie (po 1 sekundě)

// ✅ Řešení 2: bind()
const boundGreet = person.greet.bind(person);
setTimeout(boundGreet, 1000);
// → Hi, I'm Charlie (po 1 sekundě)

// ✅ Řešení 3: bind přímo
setTimeout(person.greet.bind(person), 1000);
// → Hi, I'm Charlie (po 1 sekundě)

Co se stalo?

  • Arrow funkce wrapper: () => person.greet() zachová kontext
  • bind(): vytvoří novou funkci s pevně nastaveným this
  • Oba způsoby zachovají this = person

Příklad 5: Arrow funkce NEMÁ vlastní this

const person1 = {
  name: 'David',

  greet: function() {
    console.log(`(normal) Hi, I'm ${this.name}`);
  }
};

const person2 = {
  name: 'Eve',

  greet: () => {
    console.log(`(arrow) Hi, I'm ${this.name}`);
  }
};

person1.greet();
// → (normal) Hi, I'm David ✅

person2.greet();
// → (arrow) Hi, I'm undefined ❌

// Arrow funkce má this z okolního scope (často global)

Co se stalo?

  • Normální funkce má vlastní this = objekt
  • Arrow funkce NEMÁ vlastní this - použije this z okolí
  • NEPOUŽÍVEJ arrow funkce jako metody objektu!

Příklad 6: call, apply, bind - explicitní nastavení this

function introduce(greeting, punctuation) {
  console.log(`${greeting}, I'm ${this.name}${punctuation}`);
}

const person1 = { name: 'Frank' };
const person2 = { name: 'Grace' };

// call(thisArg, arg1, arg2, ...)
introduce.call(person1, 'Hello', '!');
// → Hello, I'm Frank!

introduce.call(person2, 'Hi', '.');
// → Hi, I'm Grace.

// apply(thisArg, [args])
introduce.apply(person1, ['Hey', '!!!']);
// → Hey, I'm Frank!!!

// bind(thisArg) - vytvoří novou funkci
const introduceFrank = introduce.bind(person1);
introduceFrank('Greetings', '.');
// → Greetings, I'm Frank.

// bind s částečnou aplikací argumentů
const greetFrank = introduce.bind(person1, 'Hello');
greetFrank('!');
// → Hello, I'm Frank!

Co se stalo?

  • call(thisArg, ...args) - zavolá funkci s explicitním this
  • apply(thisArg, [args]) - jako call, ale argumenty jako pole
  • bind(thisArg) - vytvoří novou funkci s pevným this
  • Užitečné pro explicitní nastavení kontextu

TypeScript

TypeScript přidává typovou kontrolu this pomocí this parametru.

Stejné příklady s typy

// Interface s this parametrem
interface Person {
  name: string;
  age: number;
  greet(this: Person): void;
}

const person: Person = {
  name: 'Alice',
  age: 25,

  greet(this: Person) {
    // TypeScript ví, že this je Person
    console.log(`Hi, I'm ${this.name}`);
  }
};

person.greet();  // ✅ OK

// Ztráta this - TypeScript varuje
const greetFn = person.greet;
// greetFn();  // ❌ Error: The 'this' context of type 'void' is not assignable to method's 'this' of type 'Person'

// Explicitní this typ v standalone funkci
function introduce(this: { name: string }, greeting: string) {
  console.log(`${greeting}, I'm ${this.name}`);
}

const user = { name: 'Bob' };
introduce.call(user, 'Hello');  // ✅ OK

// introduce.call({ age: 30 }, 'Hi');  // ❌ Error: 'age' does not exist in type '{ name: string }'

// Arrow funkce - this z okolního scope
class Counter {
  count = 0;

  // Normální metoda - this je Counter
  increment(this: Counter) {
    this.count++;
  }

  // Arrow funkce jako property - this je Counter (lexikální)
  incrementArrow = () => {
    this.count++;
  };
}

const counter = new Counter();
counter.increment();  // ✅ OK

const incrementFn = counter.increment;
// incrementFn();  // ❌ Error: 'this' context lost

const incrementArrowFn = counter.incrementArrow;
incrementArrowFn();  // ✅ OK - arrow funkce zachová this

// Generic this type
interface Builder<T> {
  value: T;
  setValue(this: Builder<T>, value: T): this;  // Vrací this (fluent API)
}

const numberBuilder: Builder<number> = {
  value: 0,

  setValue(value) {
    this.value = value;
    return this;  // Vrátí sám sebe pro chaining
  }
};

numberBuilder.setValue(10).setValue(20);  // ✅ Chaining

TypeScript přidává:

  • Typovou kontrolu this - this: Type parametr
  • Varování při ztrátě this - upozorní na problém
  • Prevenci chyb - nemůžeš volat metodu s špatným this
  • this return type - pro fluent API (chaining)

Rozdíl JS vs TS

JavaScript:

  • this funguje bez typové kontroly
  • Ztráta this způsobí runtime chyby
  • Flexibilnější, ale nebezpečnější

TypeScript:

  • this má typovou kontrolu
  • TypeScript varuje při ztrátě this
  • Bezpečnější, prevence chyb
// JavaScript - projde, ale runtime chyba
const obj = {
  value: 10,
  getValue() {
    return this.value;
  }
};

const fn = obj.getValue;
console.log(fn());  // → undefined (ztráta this)

// TypeScript - compile error
interface Obj {
  value: number;
  getValue(this: Obj): number;
}

const obj: Obj = {
  value: 10,
  getValue() {
    return this.value;
  }
};

const fn = obj.getValue;
// fn();  // ❌ Error: The 'this' context is not assignable

Tip

💡 Používej arrow funkci pro zachování this v callbacku:

const person = {
  name: 'Alice',
  greet() {
    console.log(`Hi, I'm ${this.name}`);
  }
};

// ❌ Ztráta this
setTimeout(person.greet, 1000);

// ✅ Arrow wrapper zachová this
setTimeout(() => person.greet(), 1000);

// ✅ Nebo bind
setTimeout(person.greet.bind(person), 1000);

💡 NEPOUŽÍVEJ arrow funkce jako metody objektu:

// ❌ Arrow funkce nemá vlastní this
const obj = {
  value: 10,
  getValue: () => {
    return this.value;  // this není obj!
  }
};

// ✅ Používej normální funkci nebo method shorthand
const obj = {
  value: 10,
  getValue() {
    return this.value;
  }
};

💡 Používej this parametr v TypeScript:

// ✅ Explicitní this typ - prevence chyb
interface User {
  name: string;
  greet(this: User): void;
}

Kvíz

Co vypíše tento kód?

const obj = {
  value: 42,

  getValue() {
    return this.value;
  }
};

const fn = obj.getValue;
console.log(fn());

- To by fungovalo s obj.getValue() nebo fn.call(obj)

- - const fn = obj.getValue - uložíme metodu do proměnné

  • fn() - zavoláme funkci BEZ kontextu objektu
  • this uvnitř fn = global object (nebo undefined v strict mode)
  • global.value neexistuje → undefined
  • Ztráta this! - metoda ztratila odkaz na původní objekt

- Není to chyba, jen vrací undefined

- Neexistující vlastnost vrací undefined, ne null

Důležité: Když uložíš metodu do proměnné a zavoláš ji, ztratíš this kontext! Řešení: bind() nebo arrow wrapper.

Důležité: Když uložíš metodu do proměnné a zavoláš ji, ztratíš this kontext! Řešení: bind() nebo arrow wrapper.

🎯 Závěrečný projekt

Po dokončení všech 8 dílů vytvoříte jednoduchou Todо aplikaci v čistém JavaScriptu. Naučíte se, jak aplikovat vše, co jste se naučili, na reálný projekt.

Zobrazit podrobnosti projektu →

Připraveni začít?

Zaregistrujte se a získejte přístup ke všem dílům tohoto seriálu

Kontaktujte mě

Informace o seriálu

Obtížnost

Délka

Cca 480 minut

Počet videí

8 videí + projekty

Certifikát

Po dokončení obdržíte certifikát


Lekce v této sekci


Struktura lekcí (souborový strom)

06. Typescript specifika
  • v přípravě
08. Moduly tridy
  • v přípravě
09. React zaklady
  • v přípravě
10. React hooks
  • v přípravě
12. Nextjs server
  • v přípravě
13. Databaze auth
  • v přípravě
14. Nextjs pokrocile
  • v přípravě