Objekty jsou obvykle vytvářeny tak, aby reprezentovaly entity skutečného světa, jako jsou uživatelé, objednávky a tak dále:
let user = {
name: "John",
age: 30
};
A v reálném světě může uživatel jednat :vybrat něco z nákupního košíku, přihlášení, odhlášení atd.
Akce jsou v JavaScriptu reprezentovány funkcemi ve vlastnostech.
Příklady metod
Pro začátek se naučíme user
pozdravit:
let user = {
name: "John",
age: 30
};
user.sayHi = function() {
alert("Hello!");
};
user.sayHi(); // Hello!
Zde jsme právě použili funkční výraz k vytvoření funkce a přiřazení k vlastnosti user.sayHi
objektu.
Pak to můžeme nazvat jako user.sayHi()
. Uživatel nyní může mluvit!
Funkce, která je vlastností objektu, se nazývá jeho metoda .
Takže tady máme metodu sayHi
objektu user
.
Samozřejmě bychom mohli jako metodu použít předem deklarovanou funkci, jako je tato:
let user = {
// ...
};
// first, declare
function sayHi() {
alert("Hello!");
}
// then add as a method
user.sayHi = sayHi;
user.sayHi(); // Hello!
Objektově orientované programování Když píšeme náš kód pomocí objektů k reprezentaci entit, nazývá se to objektově orientované programování, stručně:„OOP“.
OOP je velká věc, zajímavá vlastní věda. Jak vybrat ty správné subjekty? Jak zorganizovat interakci mezi nimi? To je architektura a na toto téma existují skvělé knihy, jako například „Design Patterns:Elements of Reusable Object-Oriented Software“ od E. Gamma, R. Helma, R. Johnsona, J. Vissidese nebo „Object-Oriented Analysis and Design with Applications“ od G. Boocha a další.
Zkratka metody
V objektovém literálu existuje kratší syntaxe pro metody:
// these objects do the same
user = {
sayHi: function() {
alert("Hello");
}
};
// method shorthand looks better, right?
user = {
sayHi() { // same as "sayHi: function(){...}"
alert("Hello");
}
};
Jak bylo ukázáno, můžeme vynechat "function"
a stačí napsat sayHi()
.
Abych řekl pravdu, zápisy nejsou zcela totožné. Existují jemné rozdíly související s dědičností objektů (budou pokryty později), ale zatím na nich nezáleží. Téměř ve všech případech je preferována kratší syntaxe.
„toto“ v metodách
Je běžné, že objektová metoda potřebuje ke své práci přistupovat k informacím uloženým v objektu.
Například kód v user.sayHi()
může vyžadovat název user
.
Pro přístup k objektu může metoda použít this
klíčové slovo.
Hodnota this
je objekt „před tečkou“, ten, který se používá k volání metody.
Například:
let user = {
name: "John",
age: 30,
sayHi() {
// "this" is the "current object"
alert(this.name);
}
};
user.sayHi(); // John
Zde během provádění user.sayHi()
, hodnota this
bude user
.
Technicky je také možné přistupovat k objektu bez this
, odkazem na něj prostřednictvím vnější proměnné:
let user = {
name: "John",
age: 30,
sayHi() {
alert(user.name); // "user" instead of "this"
}
};
…Ale takový kód je nespolehlivý. Pokud se rozhodneme zkopírovat user
do jiné proměnné, např. admin = user
a přepište user
s něčím jiným, pak přistoupí k nesprávnému objektu.
To je ukázáno níže:
let user = {
name: "John",
age: 30,
sayHi() {
alert( user.name ); // leads to an error
}
};
let admin = user;
user = null; // overwrite to make things obvious
admin.sayHi(); // TypeError: Cannot read property 'name' of null
Pokud bychom použili this.name
místo user.name
uvnitř alert
, pak by kód fungoval.
„toto“ není vázáno
V JavaScriptu klíčové slovo this
se chová na rozdíl od většiny ostatních programovacích jazyků. Může být použit v jakékoli funkci, i když to není metoda objektu.
V následujícím příkladu není žádná syntaktická chyba:
function sayHi() {
alert( this.name );
}
Hodnota this
se vyhodnocuje během běhu v závislosti na kontextu.
Například zde je stejná funkce přiřazena dvěma různým objektům a má odlišné „toto“ ve volání:
let user = { name: "John" };
let admin = { name: "Admin" };
function sayHi() {
alert( this.name );
}
// use the same function in two objects
user.f = sayHi;
admin.f = sayHi;
// these calls have different this
// "this" inside the function is the object "before the dot"
user.f(); // John (this == user)
admin.f(); // Admin (this == admin)
admin['f'](); // Admin (dot or square brackets access the method – doesn't matter)
Pravidlo je jednoduché:if obj.f()
je voláno a poté this
je obj
během volání f
. Takže je to buď user
nebo admin
ve výše uvedeném příkladu.
this == undefined
Funkci můžeme dokonce volat zcela bez objektu:
function sayHi() {
alert(this);
}
sayHi(); // undefined
V tomto případě this
je undefined
v přísném režimu. Pokud se pokusíme získat přístup k this.name
, dojde k chybě.
V nepřísném režimu hodnota this
v takovém případě to bude globální objekt (window
v prohlížeči, k němu se dostaneme později v kapitole Globální objekt). Toto je historické chování, které "use strict"
opravy.
Obvykle je takové volání chybou programování. Pokud je zde this
uvnitř funkce očekává, že bude volána v kontextu objektu.
this
Pokud pocházíte z jiného programovacího jazyka, pak jste pravděpodobně zvyklí na myšlenku "svázaného this
", kde metody definované v objektu mají vždy this
odkazující na tento objekt.
V JavaScriptu this
je „free“, jeho hodnota se vyhodnocuje při volání a nezávisí na tom, kde byla metoda deklarována, ale spíše na tom, jaký objekt je „před tečkou“.
Koncept run-time vyhodnocen this
má plusy i mínusy. Na jedné straně lze funkci znovu použít pro různé objekty. Na druhou stranu větší flexibilita vytváří více možností pro chyby.
Zde není naším postojem posuzovat, zda je toto rozhodnutí o návrhu jazyka dobré nebo špatné. Pochopíme, jak s tím pracovat, jak získat výhody a vyhnout se problémům.
Funkce šipek nemají žádné „toto“
Funkce šipek jsou speciální:nemají „vlastní“ this
. Pokud odkazujeme na this
z takové funkce je převzata z vnější „normální“ funkce.
Například zde arrow()
používá this
z vnějšího user.sayHi()
metoda:
let user = {
firstName: "Ilya",
sayHi() {
let arrow = () => alert(this.firstName);
arrow();
}
};
user.sayHi(); // Ilya
To je speciální funkce funkcí šipek, je to užitečné, když ve skutečnosti nechceme mít samostatný this
, ale spíše to brát z vnějšího kontextu. Později v kapitole Revidované funkce šipek půjdeme hlouběji do funkcí šipek.
Shrnutí
- Funkce, které jsou uloženy ve vlastnostech objektu, se nazývají „metody“.
- Metody umožňují objektům „chovat se“ jako
object.doSomething()
. - Metody mohou odkazovat na objekt jako
this
.
Hodnota this
je definován za běhu.
- Když je funkce deklarována, může používat
this
, ale tothis
nemá žádnou hodnotu, dokud není funkce volána. - Funkci lze kopírovat mezi objekty.
- Pokud je funkce volána v syntaxi „metody“:
object.method()
, hodnotathis
během hovoru jeobject
.
Upozorňujeme, že funkce šipek jsou speciální:nemají this
. Když this
je přístupná uvnitř funkce šipky, je převzata zvenčí.